Workflow for iterative building of a time series model.
We analyse the relative number of births per day in USA 1969-1988 using Gaussian process time series model with several model components that can explain the long term, seasonal, weekly, day of year, and special floatind day variation.
Models for relative number of birthdays
As the relative number of births is positive it’s natural to model the logarithm value. The generic form of the models is \[
y \sim \mbox{normal}(f(x), \sigma),
\] where \(f\) is different and gradually more complex function conditional on \(x\) that includes running day number, day of year, day of week and eventually some special floating US bank holidays.
Model 1: Slow trend
The model 1 is just the slow trend over the years using Hilbert space basis function approximated Gaussian process \[
f = \mbox{intercept} + f_1\\
\mbox{intercept} \sim \mbox{normal}(0,1)\\
f_1 \sim \mbox{GP}(0,K_1)
\] where GP has exponentiated quadratic covariance function.
In this phase the code from Riutort-Mayol et al.(2020) was cleaned and written to be more efficient, but only the one GP component was included to make the testing easier. Although the code was made more efficient, the aim wasn’t to make it the fastest possible as the later model changes may have bigger effect on the performance (it’s good o avoid premature optimization). We also use quite small number of basis functions to make the code run faster, and only later examine more carefully whether the number of basis function is sufficient compared to the posterior of the length scale (see, Riutort-Mayol et al., 2020).
<<<<<<< HEAD
Compile Stan model gpbf1.stan which includes gpbasisfun_functions.stan
=======
Compile Stan model gpbf1.stan which includes gpbasisfun_functions1.stan
>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
model1 <- cmdstan_model(stan_file = root("Birthdays", "gpbf1.stan"),
include_paths = root("Birthdays"))
Data to be passed to Stan
standata1 <- list(x=data$id,
y=log(data$births_relative100),
N=length(data$id),
c_f1=1.5, # factor c of basis functions for GP for f1
M_f1=10) # number of basis functions for GP for f1
As the basis function approximation and priors restrict the complexity of GP, we can safely use optimization to get a very quick initial result to check that the model code is computing what we intended. As there are only 14 parameters and 7305 observations it’s likely that the posterior is close to normal (in unconstrained space). In this case the optimization takes less than one second while MCMC sampling with default options would have taken several minutes. Although this result can be useful in a quick workflow, the result should not be used as the final result.
opt1 <- model1$optimize(data = standata1, init=0, algorithm='bfgs')
Check whether parameters have reasonable values
odraws1 <- opt1$draws()
subset(odraws1, variable=c('intercept','sigma_f1','lengthscale_f1','sigma'))
<<<<<<< HEAD
# A draws_matrix: 1 draws, and 4 variables
=======
# A draws_matrix: 1 iterations, 1 chains, and 4 variables
>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
variable
draw intercept sigma_f1 lengthscale_f1 sigma
1 -0.11 2.2 0.23 0.81
Compare the model to the data
oEf <- exp(as.numeric(subset(odraws1, variable='f')))
data %>%
mutate(oEf = oEf) %>%
ggplot(aes(x=date, y=births_relative100)) +
geom_point(color=set1[2], alpha=0.2) +
geom_line(aes(y=oEf), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births")
<<<<<<< HEAD

=======

>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
After we get the model working using optimization we can compare the result to using short MCMC chains which will also provide us additional information on speed of different code implementations for the same model. We intentionally use just 1/10th length from the usual recommendation, as during the iterative model building a rough results are sufficient. When testing the code we initially used just one chain, but at this point running four chains with four core CPU doesn’t add much to the wall clock time, but gives more information of how easy it is sample from the posterior and can reveal if there are multiple modes. Although the result from short chains can be useful in a quick workflow, the result should not be used as th final result.
fit1 <- model1$sample(data=standata1, iter_warmup=100, iter_sampling=100,
chains=4, parallel_chains=4, seed=3891)
Depending on the random seed and luck, we sometimes observed that some of the chains got stuck in different modes. We could see this in high Rhat and low ESS diagnostic values.
draws1 <- fit1$draws()
summarise_draws(subset(draws1, variable=c('intercept','sigma_f1','lengthscale_f1','sigma')))
<<<<<<< HEAD
# A tibble: 4 x 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 intercept -0.20 -0.23 0.38 0.26 -0.79 0.51 1.2 76. 89.
2 sigma_f1 1.5 1.3 0.39 0.30 0.99 2.1 1.6 7.6 12.
3 lengthscale_f1 1.8 0.32 2.6 0.14 0.14 6.4 1.6 7.5 35.
4 sigma 0.89 0.82 0.13 0.011 0.81 1.1 1.6 7.2 12.
Examining the trace plots shows the multimodality clearly.
mcmc_trace(draws1, regex_pars=c('intercept','sigma_f1','lengthscale_f1','sigma'))

=======
# A tibble: 4 × 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 intercept -0.17 -0.25 0.34 0.28 -0.70 0.45 1.2 18. NA
2 sigma_f1 1.7 1.7 0.36 0.48 1.1 2.1 1.3 12. NA
3 lengthscale_f1 1.8 0.27 2.7 0.17 0.097 6.4 1.7 7.0 NA
4 sigma 0.90 0.82 0.15 0.010 0.81 1.2 1.6 7.4 NA
Examining the trace plots shows the multimodality clearly.
mcmc_trace(draws1, regex_pars=c('intercept','sigma_f1','lengthscale_f1','sigma'))

>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
In this case it was easy to figure out that some of the chains got stuck in qualitatively much worse modes. We don’t in general recommend to start from the mode as the mode is not usually representative point in hierarchical model posterior or in high dimensional posterior, but we can use this again to speed up the iterative model building as long as we check that the optimization result is sensible and later do more careful inference. Although the result from short chains can be useful in a quick workflow, the result should not be used as the final result.
init1 <- sapply(c('intercept','sigma_f1','lengthscale_f1','beta_f1','sigma'),
function(variable) {as.numeric(subset(odraws1, variable=variable))})
fit1 <- model1$sample(data=standata1, iter_warmup=100, iter_sampling=100,
chains=4, parallel_chains=4,
init=function() { init1 })
We now observe better Rhat and ESS diagnostic values, although due to very short chains they are not yet perfect. We are likely to also observe Hamiltonian Monte Carlo divergences and treedepth exceedences in dynamic building of the Hamiltonian trajectory, but there is no need to worry about those as long as the model results are qualitatively sensible as these computational issues can also go away when the model itself is improved. In all the following short MCMC samplings we get some or many divergences and usually very large number of treedepth exceedences. Divergences indicate possible bias and should be eventually investigated carefully. Treedepth exceedences indicate strong posterior dependencies and slow mixing and sometimes the posterior can be much improved by changing the parameterization or priors, but as the treedepth exceedences don’t indicate bias there is no need for more careful analysis if the resulting ESS and MCSE values are good for the purpose in hand. We’ll come back later to more careful analysis of the final models.
draws1 <- fit1$draws()
summarise_draws(subset(draws1, variable=c('intercept','sigma_f1','lengthscale_f1','sigma')))
<<<<<<< HEAD
# A tibble: 4 x 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 intercept -0.16 -0.18 0.43 0.43 -0.82 0.61 1.1 103. 137.
2 sigma_f1 1.3 1.3 0.22 0.22 0.92 1.6 1.0 150. 186.
3 lengthscale_f1 0.27 0.27 0.079 0.080 0.15 0.41 1.0 184. 141.
4 sigma 0.81 0.81 0.0063 0.0063 0.80 0.83 1.0 425. 287.
Trace plot shows slow mixing but no multimodality.
mcmc_trace(draws1, regex_pars=c('intercept','sigma_f1','lengthscale_f1','sigma'))

=======
# A tibble: 4 × 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 intercept -0.14 -0.088 0.45 0.38 -0.93 0.59 1.0 86. NA
2 sigma_f1 1.5 1.5 0.35 0.35 1.0 2.1 1.0 150. NA
3 lengthscale_f1 0.25 0.24 0.090 0.094 0.096 0.39 1.0 162. NA
4 sigma 0.82 0.82 0.0060 0.0059 0.81 0.82 1.0 462. NA
Trace plot shows slow mixing but no multimodality.
mcmc_trace(draws1, regex_pars=c('intercept','sigma_f1','lengthscale_f1','sigma'))

>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
The model result from short MCMC chains looks very similar to the optimization result.
draws1 <- as_draws_matrix(draws1)
Ef <- exp(apply(subset(draws1, variable='f'), 2, median))
data %>%
mutate(Ef = Ef) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_line(aes(y=Ef), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births")
<<<<<<< HEAD

=======

>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
If we compare the result from short sampling to optimizing, we don’t see practical difference in the predictions (although we see later more differences between optimization and MCMC).
data %>%
mutate(Ef = Ef,
oEf = oEf) %>%
ggplot(aes(x=Ef, y=oEf)) + geom_point(color=set1[2]) +
geom_abline() +
labs(x="Ef from short Markov chain", y="Ef from optimizing")
<<<<<<< HEAD

=======

The original notebook continued using the gpbasisfun_functions1.stan used above. Much later Nikolas Siccha examined more carefully the posterior correlations and noticed strong correlation between intercept and the first basis function. Stan’s dynamic HMC is so efficient that the inference is succesful anyway. While Nikolas suggested removing the intercept term, the better solution is to make the basis functions to have zero means. We should have noticed to do that already for Riutort-Mayol et al., (2020) paper, but missed that.
File gpbasisfun_functions.stan has the fixed code which makes the basis functions to have zero mean.
model1b <- cmdstan_model(stan_file = root("Birthdays", "gpbf1b.stan"),
include_paths = root("Birthdays"))
fit1b <- model1b$sample(data=standata1, iter_warmup=100, iter_sampling=100,
chains=4, parallel_chains=4, seed=3891)
With the better posterior geometry, it is unlikely that we get stuck in a local mode even with the random inits.
draws1b <- fit1b$draws()
summarise_draws(subset(draws1b, variable=c('intercept','sigma_f1','lengthscale_f1','sigma')))
# A tibble: 4 × 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 intercept 0.00094 0.0013 0.010 0.0099 -0.015 0.018 1.0 386. 301.
2 sigma_f1 1.6 1.6 0.38 0.36 1.1 2.2 1.0 181. NA
3 lengthscale_f1 0.27 0.27 0.11 0.12 0.099 0.45 1.1 110. NA
4 sigma 0.82 0.82 0.0067 0.0068 0.80 0.83 1.0 465. NA
Examining the trace plots shows better behavior.
mcmc_trace(draws1b, regex_pars=c('intercept','sigma_f1','lengthscale_f1','sigma'))

The remaining models use the zero mean basis functions which produce better posterior geometry. We’ll however keep using the optimization inits for the remaining samplings to get some speed-up.
>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
Model 2: Slow trend + yearly seasonal trend
The model 2 adds yearly seasonal trend using GP with periodic covariance function. \[
f = \mbox{intercept} + f_1 + f_2 \\
\mbox{intercept} \sim \mbox{normal}(0,1)\\
f_1 \sim \mbox{GP}(0,K_1)\\
f_2 \sim \mbox{GP}(0,K_2)
\] where the first GP uses the exponentiated quadratic covariance function, and the second one a periodic covariance function. Most years have 365 calendar days and every four years (during the data range) there are 366 days, and thus we simplify and use period of 365.25 for the periodic component,
The first version of model 2 with the added periodic component following from Riutort-Mayol (2020) turned out be very slow. With the default MCMC options the inference would have taken hours, but with the short chains it was possible to infer that something has to be wrong. The model output was sensible, but diagnostics indicated very slow mixing. By more careful examination of the model it turned out that the periodic component was including another intercept term and with two intercept terms their sum was well informed by the data, but individually they were not well informed and thus the posteriors were wide, which lead to very slow mixing. This bad model is not shown here, but the optimization, short MCMC chains and sampling diagnostic tools were crucial for fast experimentation and solving the problem.
Compile Stan model 2 (the fixed version) gpbf2.stan
model2 <- cmdstan_model(stan_file = root("Birthdays", "gpbf2.stan"),
include_paths = root("Birthdays"))
Data to be passed to Stan
standata2 <- list(x=data$id,
y=log(data$births_relative100),
N=length(data$id),
c_f1=1.5, # factor c of basis functions for GP for f1
M_f1=10, # number of basis functions for GP for f1
J_f2=20) # number of basis functions for periodic f2
Optimizing is faster than sampling (although this result can be useful in a quick workflow, the result should not be used as the final result).
opt2 <- model2$optimize(data=standata2, init=0, algorithm='bfgs')
Check whether parameters have reasonable values
odraws2 <- opt2$draws()
subset(odraws2, variable=c('intercept','sigma_','lengthscale_','sigma'), regex=TRUE)
<<<<<<< HEAD
# A draws_matrix: 1 draws, and 6 variables
=======
# A draws_matrix: 1 iterations, 1 chains, and 6 variables
>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
variable
draw intercept sigma_f1 sigma_f2 lengthscale_f1 lengthscale_f2 sigma
1 9.6e-08 2.1 1.3 0.23 0.086 0.75
Compare the model to the data
Ef <- exp(as.numeric(subset(odraws2, variable='f')))
Ef1 <- as.numeric(subset(odraws2, variable='f1'))
Ef1 <- exp(Ef1 - mean(Ef1) + mean(log(data$births_relative100)))
Ef2 <- as.numeric(subset(odraws2, variable='f2'))
Ef2 <- exp(Ef2 - mean(Ef2) + mean(log(data$births_relative100)))
pf <- data %>%
mutate(Ef = Ef) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_line(aes(y=Ef), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births")
pf1 <- data %>%
mutate(Ef1 = Ef1) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_line(aes(y=Ef1), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births")
pf2 <- data %>%
mutate(Ef2 = Ef2) %>%
group_by(day_of_year2) %>%
summarise(meanbirths=mean(births_relative100), meanEf2=mean(Ef2)) %>%
ggplot(aes(x=as.Date("1987-12-31")+day_of_year2, y=meanbirths)) + geom_point(color=set1[2], alpha=0.2) +
scale_x_date(date_breaks = "1 month", date_labels = "%b") +
geom_line(aes(y=meanEf2), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of year")
pf / (pf1 + pf2)
<<<<<<< HEAD

=======

>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
Sample short chains using the optimization result as initial values (although the result from short chains can be useful in a quick workflow, the result should not be used as the final result).
init2 <- sapply(c('intercept','lengthscale_f1','lengthscale_f2','sigma_f1','sigma_f2','sigma','beta_f1','beta_f2'),
function(variable) {as.numeric(subset(odraws2, variable=variable))})
fit2 <- model2$sample(data=standata2, iter_warmup=100, iter_sampling=100,
chains=4, parallel_chains=4,
init=function() { init2 })
Check whether parameters have reasonable values
draws2 <- fit2$draws()
summarise_draws(subset(draws2, variable=c('intercept','sigma_','lengthscale_','sigma'), regex=TRUE))
<<<<<<< HEAD
# A tibble: 6 x 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 intercept -0.051 -0.057 0.45 0.46 -0.69 0.60 1.0 463. 348.
2 sigma_f1 1.5 1.4 0.34 0.32 0.97 2.2 1.0 317. 317.
3 sigma_f2 0.30 0.29 0.059 0.051 0.22 0.41 1.0 233. 285.
4 lengthscale_… 0.26 0.26 0.11 0.13 0.081 0.44 1.0 519. 266.
5 lengthscale_… 0.24 0.24 0.024 0.023 0.21 0.29 1.0 195. 373.
6 sigma 0.76 0.76 0.0067 0.0069 0.75 0.77 1.0 384. 338.
=======
# A tibble: 6 × 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 intercept -1.7e-4 -8.8e-4 0.0088 0.0086 -0.014 0.016 1.0 337. NA
2 sigma_f1 1.5e+0 1.4e+0 0.35 0.33 1.0 2.1 1.0 247. NA
3 sigma_f2 2.9e-1 2.8e-1 0.056 0.045 0.21 0.40 1.0 287. NA
4 lengthscal… 2.5e-1 2.4e-1 0.10 0.11 0.080 0.41 1.0 684. NA
5 lengthscal… 2.4e-1 2.4e-1 0.025 0.023 0.21 0.29 1.0 218. NA
6 sigma 7.6e-1 7.6e-1 0.0061 0.0061 0.75 0.77 1.0 433. 315.
>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
Compare the model to the data
draws2 <- as_draws_matrix(draws2)
Ef <- exp(apply(subset(draws2, variable='f'), 2, median))
Ef1 <- apply(subset(draws2, variable='f1'), 2, median)
Ef1 <- exp(Ef1 - mean(Ef1) + mean(log(data$births_relative100)))
Ef2 <- apply(subset(draws2, variable='f2'), 2, median)
Ef2 <- exp(Ef2 - mean(Ef2) + mean(log(data$births_relative100)))
pf <- data %>%
mutate(Ef = Ef) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_line(aes(y=Ef), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births")
pf1 <- data %>%
mutate(Ef1 = Ef1) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_line(aes(y=Ef1), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births")
pf2 <- data %>%
mutate(Ef2 = Ef2) %>%
group_by(day_of_year2) %>%
summarise(meanbirths=mean(births_relative100), meanEf2=mean(Ef2)) %>%
ggplot(aes(x=as.Date("1987-12-31")+day_of_year2, y=meanbirths)) + geom_point(color=set1[2], alpha=0.2) +
scale_x_date(date_breaks = "1 month", date_labels = "%b") +
geom_line(aes(y=meanEf2), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of year")
pf / (pf1 + pf2)
<<<<<<< HEAD

=======

>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
Seasonal component has reasonable fit to the data.
Model 3: Slow trend + yearly seasonal trend + day of week
Based on the quick plotting of the data above, day of week has a clear effect and there are less babies born on Saturday and Sunday. This can be taken into account with simple additive coefficients. We fix the effect of Monday to 0 and have additional coefficients for other weekdays. \[
f = \mbox{intercept} + f_1 + f_2 + \beta_{\mbox{day of week}} \\
\mbox{intercept} \sim \mbox{normal}(0,1)\\
f_1 \sim \mbox{GP}(0,K_1)\\
f_2 \sim \mbox{GP}(0,K_2)\\
\beta_{\mbox{day of week}} = 0 \quad \mbox{if day of week is Monday}\\
\beta_{\mbox{day of week}} \sim \mbox{normal}(0,1) \quad \mbox{if day of week is not Monday}
\]
Compile Stan model 3 gpbf3.stan
model3 <- cmdstan_model(stan_file = root("Birthdays", "gpbf3.stan"),
include_paths = root("Birthdays"))
Data to be passed to Stan
standata3 <- list(x=data$id,
y=log(data$births_relative100),
N=length(data$id),
c_f1=1.5, # factor c of basis functions for GP for f1
M_f1=10, # number of basis functions for GP for f1
J_f2=20, # number of basis functions for periodic f2
day_of_week=data$day_of_week)
Optimizing is faster than sampling (although this result can be useful in a quick workflow, the result should not be used as the final result).
opt3 <- model3$optimize(data=standata3, init=0, algorithm='bfgs')
Check whether parameters have reasonable values
odraws3 <- opt3$draws()
subset(odraws3, variable=c('intercept','sigma_','lengthscale_','sigma'), regex=TRUE)
<<<<<<< HEAD
# A draws_matrix: 1 draws, and 6 variables
variable
draw intercept0 sigma_f1 sigma_f2 lengthscale_f1 lengthscale_f2 sigma
1 0.37 2.1 1.3 0.23 0.086 0.34
subset(odraws3, variable=c('beta_f3'))
# A draws_matrix: 1 draws, and 6 variables
=======
# A draws_matrix: 1 iterations, 1 chains, and 6 variables
variable
draw intercept0 sigma_f1 sigma_f2 lengthscale_f1 lengthscale_f2 sigma
1 0.28 2.1 1.3 0.23 0.086 0.34
subset(odraws3, variable=c('beta_f3'))
# A draws_matrix: 1 iterations, 1 chains, and 6 variables
>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
variable
draw beta_f3[1] beta_f3[2] beta_f3[3] beta_f3[4] beta_f3[5] beta_f3[6]
1 0.36 0.12 0.04 0.17 -1.1 -1.5
Compare the model to the data
Ef <- exp(as.numeric(subset(odraws3, variable='f')))
Ef1 <- as.numeric(subset(odraws3, variable='f1'))
Ef1 <- exp(Ef1 - mean(Ef1) + mean(log(data$births_relative100)))
Ef2 <- as.numeric(subset(odraws3, variable='f2'))
Ef2 <- exp(Ef2 - mean(Ef2) + mean(log(data$births_relative100)))
Ef_day_of_week <- as.numeric(subset(odraws3, variable='f_day_of_week'))
Ef_day_of_week <- exp(Ef_day_of_week - mean(Ef_day_of_week) + mean(log(data$births_relative100)))
pf <- data %>%
mutate(Ef = Ef) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_line(aes(y=Ef), color=set1[1], alpha=0.75) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births")
pf1 <- data %>%
mutate(Ef1 = Ef1) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_line(aes(y=Ef1), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births")
pf2 <- data %>%
mutate(Ef2 = Ef2) %>%
group_by(day_of_year2) %>%
summarise(meanbirths=mean(births_relative100), meanEf2=mean(Ef2)) %>%
ggplot(aes(x=as.Date("1987-12-31")+day_of_year2, y=meanbirths)) + geom_point(color=set1[2], alpha=0.2) +
scale_x_date(date_breaks = "1 month", date_labels = "%b") +
geom_line(aes(y=meanEf2), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of year")
pf3 <- ggplot(data=data, aes(x=day_of_week, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
scale_x_continuous(breaks = 1:7, labels=c('Mon','Tue','Wed','Thu','Fri','Sat','Sun')) +
geom_line(data=data.frame(x=1:7,y=Ef_day_of_week), aes(x=x, y=Ef_day_of_week), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of week")
(pf + pf1) / (pf2 + pf3)
<<<<<<< HEAD

=======

>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
Sample short chains using the optimization result as initial values (although the result from short chains can be useful in a quick workflow, the result should not be used as the final result).
init3 <- sapply(c('intercept0','lengthscale_f1','lengthscale_f2','sigma_f1','sigma_f2','sigma',
'beta_f1','beta_f2','beta_f3'),
function(variable) {as.numeric(subset(odraws3, variable=variable))})
fit3 <- model3$sample(data=standata3, iter_warmup=100, iter_sampling=100,
chains=4, parallel_chains=4,
init=function() { init3 })
Check whether parameters have reasonable values
draws3 <- fit3$draws()
summarise_draws(subset(draws3, variable=c('intercept','sigma_','lengthscale_','sigma'), regex=TRUE))
<<<<<<< HEAD
# A tibble: 6 x 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 intercept0 0.34 0.28 0.53 0.50 -0.42 1.3 1.1 153. 60.
2 sigma_f1 1.5 1.5 0.37 0.33 1.0 2.2 1.0 312. 289.
3 sigma_f2 0.29 0.28 0.045 0.044 0.22 0.36 1.0 273. 312.
4 lengthscale_f1 0.24 0.24 0.10 0.12 0.086 0.41 1.0 385. 303.
5 lengthscale_f2 0.21 0.21 0.018 0.020 0.18 0.24 1.0 134. 276.
6 sigma 0.34 0.34 0.0028 0.0030 0.33 0.34 1.0 333. 248.
summarise_draws(subset(draws3, variable=c('beta_f3')))
# A tibble: 6 x 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 beta_f3[1] 0.36 0.36 0.016 0.016 0.33 0.38 1.0 365. 302.
2 beta_f3[2] 0.13 0.13 0.016 0.016 0.097 0.15 1.0 408. 308.
3 beta_f3[3] 0.040 0.040 0.017 0.017 0.011 0.068 1.0 405. 270.
4 beta_f3[4] 0.17 0.17 0.017 0.017 0.15 0.20 1.0 371. 340.
5 beta_f3[5] -1.1 -1.1 0.016 0.016 -1.1 -1.1 1.0 366. 336.
6 beta_f3[6] -1.5 -1.5 0.016 0.019 -1.6 -1.5 1.0 421. 316.
=======
# A tibble: 6 × 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 intercept0 0.28 0.28 0.010 0.0097 0.26 0.30 1.0 227. NA
2 sigma_f1 1.5 1.5 0.33 0.30 1.1 2.2 1.0 277. NA
3 sigma_f2 0.29 0.29 0.051 0.047 0.22 0.39 1.0 203. NA
4 lengthscale_f1 0.25 0.25 0.10 0.12 0.090 0.42 1.0 392. NA
5 lengthscale_f2 0.21 0.21 0.019 0.018 0.18 0.24 1.0 141. NA
6 sigma 0.34 0.34 0.0028 0.0027 0.33 0.34 1.0 409. 230.
summarise_draws(subset(draws3, variable=c('beta_f3')))
# A tibble: 6 × 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 beta_f3[1] 0.36 0.35 0.015 0.015 0.33 0.38 1.0 361. 279.
2 beta_f3[2] 0.12 0.12 0.015 0.014 0.10 0.15 1.0 305. NA
3 beta_f3[3] 0.040 0.041 0.013 0.013 0.019 0.063 1.0 339. 262.
4 beta_f3[4] 0.17 0.17 0.014 0.012 0.15 0.20 1.0 314. NA
5 beta_f3[5] -1.1 -1.1 0.015 0.015 -1.1 -1.1 1.0 263. 329.
6 beta_f3[6] -1.5 -1.5 0.014 0.014 -1.5 -1.5 1.0 357. NA
>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
Compare the model to the data
draws3 <- as_draws_matrix(draws3)
Ef <- exp(apply(subset(draws3, variable='f'), 2, median))
Ef1 <- apply(subset(draws3, variable='f1'), 2, median)
Ef1 <- exp(Ef1 - mean(Ef1) + mean(log(data$births_relative100)))
Ef2 <- apply(subset(draws3, variable='f2'), 2, median)
Ef2 <- exp(Ef2 - mean(Ef2) + mean(log(data$births_relative100)))
Ef_day_of_week <- apply(subset(draws3, variable='f_day_of_week'), 2, median)
Ef_day_of_week <- exp(Ef_day_of_week - mean(Ef_day_of_week) + mean(log(data$births_relative100)))
pf <- data %>%
mutate(Ef = Ef) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_line(aes(y=Ef), color=set1[1], alpha=0.75) +
labs(x="Date", y="Relative number of births")
pf1 <- data %>%
mutate(Ef1 = Ef1) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_line(aes(y=Ef1), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births")
pf2 <- data %>%
mutate(Ef2 = Ef2) %>%
group_by(day_of_year2) %>%
summarise(meanbirths=mean(births_relative100), meanEf2=mean(Ef2)) %>%
ggplot(aes(x=as.Date("1987-12-31")+day_of_year2, y=meanbirths)) + geom_point(color=set1[2], alpha=0.2) +
scale_x_date(date_breaks = "1 month", date_labels = "%b") +
geom_line(aes(y=meanEf2), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of year")
pf3 <- ggplot(data=data, aes(x=day_of_week, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
scale_x_continuous(breaks = 1:7, labels=c('Mon','Tue','Wed','Thu','Fri','Sat','Sun')) +
geom_line(data=data.frame(x=1:7,y=Ef_day_of_week), aes(x=x, y=Ef_day_of_week), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of week")
(pf + pf1) / (pf2 + pf3)
<<<<<<< HEAD

=======

>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
Weekday effects are easy to estimate as there are about thousand observations per weekday.
Model 4: long term smooth + seasonal + weekday with increasing magnitude
Looking at the time series of whole data we see the dots representing the daily values forming three branches that are getting further away from each other. In previous analysis (BDA3) we also had a model component allowing gradually changing effect for day of week and did observe that the effect of Saturday and Sunday did get stronger in time. The next model includes time dependent magnitude component for the day of week effect. \[
f = \mbox{intercept} + f_1 + f_2 + \exp(g_3)\beta_{\mbox{day of week}} \\
\mbox{intercept} \sim \mbox{normal}(0,1)\\
f_1 \sim \mbox{GP}(0,K_1)\\
f_2 \sim \mbox{GP}(0,K_2)\\
g_3 \sim \mbox{GP}(0,K_3)\\
\beta_{\mbox{day of week}} = 0 \quad \mbox{if day of week is Monday}\\
\beta_{\mbox{day of week}} \sim \mbox{normal}(0,1) \quad \mbox{if day of week is not Monday}
\] The magnitude of the weekday effect is modelled with \(\exp(g_3)\), where \(g_3\) has GP prior with zero mean and exponentiated quadratic covariance function.
Compile Stan model 4 gpbf4.stan
model4 <- cmdstan_model(stan_file = root("Birthdays", "gpbf4.stan"),
include_paths = root("Birthdays"))
Data to be passed to Stan
standata4 <- list(x=data$id,
y=log(data$births_relative100),
N=length(data$id),
c_f1=1.5, # factor c of basis functions for GP for f1
M_f1=10, # number of basis functions for GP for f1
J_f2=20, # number of basis functions for periodic f2
c_g3=1.5, # factor c of basis functions for GP for g3
M_g3=5, # number of basis functions for GP for g3
day_of_week=data$day_of_week)
As we have increased the complexity of the model, the mode starts to be less and less representative of the posterior. We still use the optimization to check that code returns something reasonable and as initial values for MCMC, but we now stop the optimization early. By adding tol_obj=10 argument, the optimization stops when the change in the log posterior density is less than 10, which is likely to happened before reaching the mode.
opt4 <- model4$optimize(data=standata4, init=0, algorithm='bfgs', tol_obj=10)
Check whether parameters have reasonable values
odraws4 <- opt4$draws()
subset(odraws4, variable=c('intercept','sigma_','lengthscale_','sigma'), regex=TRUE)
<<<<<<< HEAD
# A draws_matrix: 1 draws, and 8 variables
=======
# A draws_matrix: 1 iterations, 1 chains, and 8 variables
>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
variable
draw intercept0 sigma_f1 sigma_f2 sigma_g3 lengthscale_f1 lengthscale_f2
1 0.27 0.64 0.46 0.28 0.32 0.28
variable
draw lengthscale_g3 sigma
<<<<<<< HEAD
1 0.74 0.32
subset(odraws4, variable=c('beta_f3'))
# A draws_matrix: 1 draws, and 6 variables
=======
1 0.72 0.32
subset(odraws4, variable=c('beta_f3'))
# A draws_matrix: 1 iterations, 1 chains, and 6 variables
>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
variable
draw beta_f3[1] beta_f3[2] beta_f3[3] beta_f3[4] beta_f3[5] beta_f3[6]
1 0.35 0.12 0.056 0.17 -1.1 -1.5
Compare the model to the data
Ef <- exp(as.numeric(subset(odraws4, variable='f')))
Ef1 <- as.numeric(subset(odraws4, variable='f1'))
Ef1 <- exp(Ef1 - mean(Ef1) + mean(log(data$births_relative100)))
Ef2 <- as.numeric(subset(odraws4, variable='f2'))
Ef2 <- exp(Ef2 - mean(Ef2) + mean(log(data$births_relative100)))
Ef_day_of_week <- as.numeric(subset(odraws4, variable='f_day_of_week'))
Ef_day_of_week <- exp(Ef_day_of_week - mean(Ef_day_of_week) + mean(log(data$births_relative100)))
Ef3 <- as.numeric(subset(odraws4, variable='f3'))
Ef3 <- exp(Ef3 - mean(Ef3) + mean(log(data$births_relative100)))
pf <- data %>%
mutate(Ef = Ef) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_line(aes(y=Ef), color=set1[1], alpha=0.75) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births")
pf1 <- data %>%
mutate(Ef1 = Ef1) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_line(aes(y=Ef1), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births")
pf2 <- data %>%
mutate(Ef2 = Ef2) %>%
group_by(day_of_year2) %>%
summarise(meanbirths=mean(births_relative100), meanEf2=mean(Ef2)) %>%
ggplot(aes(x=as.Date("1987-12-31")+day_of_year2, y=meanbirths)) + geom_point(color=set1[2], alpha=0.2) +
scale_x_date(date_breaks = "1 month", date_labels = "%b") +
geom_line(aes(y=meanEf2), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of year")
pf3 <- ggplot(data=data, aes(x=day_of_week, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
scale_x_continuous(breaks = 1:7, labels=c('Mon','Tue','Wed','Thu','Fri','Sat','Sun')) +
geom_line(data=data.frame(x=1:7,y=Ef_day_of_week), aes(x=x, y=Ef_day_of_week), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of week")
pf3b <- data %>%
mutate(Ef3 = Ef3) %>%
ggplot(aes(x=date, y=births_relative100/Ef1/Ef2*100*100)) + geom_point(color=set1[2], alpha=0.2) +
geom_point(aes(y=Ef3), color=set1[1], size=0.1) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births")
(pf + pf1) / (pf2 + pf3b)
<<<<<<< HEAD

=======

>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
Sample short chains using the early stopped optimization result as initial values (although the result from short chains can be useful in a quick workflow, the result should not be used as the final result).
init4 <- sapply(c('intercept0','lengthscale_f1','lengthscale_f2','lengthscale_g3',
'sigma_f1','sigma_f2','sigma_g3','sigma',
'beta_f1','beta_f2','beta_f3','beta_g3'),
function(variable) {as.numeric(subset(odraws4, variable=variable))})
fit4 <- model4$sample(data=standata4, iter_warmup=100, iter_sampling=100,
chains=4, parallel_chains=4,
init=function() { init4 }, refresh=10)
Check whether parameters have reasonable values
draws4 <- fit4$draws()
summarise_draws(subset(draws4, variable=c('intercept','sigma_','lengthscale_','sigma'), regex=TRUE))
<<<<<<< HEAD
# A tibble: 8 x 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 intercept0 0.31 0.34 0.48 0.47 -0.52 1.1 1.0 250. 272.
2 sigma_f1 1.5 1.5 0.33 0.33 1.1 2.1 1.0 199. 322.
3 sigma_f2 0.28 0.28 0.042 0.039 0.23 0.36 1.0 176. 322.
4 sigma_g3 0.19 0.19 0.044 0.043 0.13 0.27 1.0 517. 361.
5 lengthscale_f1 0.25 0.25 0.088 0.10 0.11 0.39 1.0 319. 301.
6 lengthscale_f2 0.20 0.20 0.017 0.016 0.18 0.23 1.0 92. 361.
7 lengthscale_g3 0.75 0.77 0.22 0.23 0.33 1.1 1.0 379. 265.
8 sigma 0.32 0.32 0.0029 0.0027 0.31 0.32 1.0 265. 180.
summarise_draws(subset(draws4, variable=c('beta_f3')))
# A tibble: 6 x 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 beta_f3[1] 0.36 0.36 0.039 0.035 0.29 0.43 1.0 387. 367.
2 beta_f3[2] 0.13 0.13 0.020 0.020 0.10 0.16 1.0 395. 294.
3 beta_f3[3] 0.050 0.049 0.015 0.015 0.025 0.076 1.0 340. 253.
4 beta_f3[4] 0.18 0.18 0.023 0.022 0.14 0.21 1.0 399. 349.
5 beta_f3[5] -1.1 -1.1 0.12 0.11 -1.4 -0.96 1.0 348. 257.
6 beta_f3[6] -1.6 -1.5 0.16 0.14 -1.9 -1.3 1.0 336. 244.
=======
# A tibble: 8 × 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 intercept0 0.28 0.28 0.0096 0.010 0.26 0.29 1.0 390. NA
2 sigma_f1 1.6 1.5 0.35 0.30 1.1 2.2 1.0 244. NA
3 sigma_f2 0.29 0.28 0.052 0.046 0.22 0.39 1.0 242. NA
4 sigma_g3 0.19 0.19 0.050 0.047 0.12 0.28 1.0 578. 412.
5 lengthscale_f1 0.26 0.25 0.098 0.11 0.10 0.42 1.0 339. NA
6 lengthscale_f2 0.20 0.20 0.018 0.017 0.18 0.23 1.0 187. NA
7 lengthscale_g3 0.75 0.77 0.20 0.20 0.40 1.1 1.0 291. NA
8 sigma 0.32 0.32 0.0024 0.0026 0.31 0.32 1.0 492. NA
summarise_draws(subset(draws4, variable=c('beta_f3')))
# A tibble: 6 × 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 beta_f3[1] 0.34 0.35 0.014 0.014 0.32 0.37 1.0 358. NA
2 beta_f3[2] 0.13 0.13 0.013 0.013 0.11 0.15 1.0 438. NA
3 beta_f3[3] 0.050 0.050 0.014 0.015 0.028 0.072 1.0 402. NA
4 beta_f3[4] 0.17 0.17 0.014 0.015 0.15 0.19 1.0 369. NA
5 beta_f3[5] -1.1 -1.1 0.014 0.013 -1.1 -1.1 1.0 366. NA
6 beta_f3[6] -1.5 -1.5 0.014 0.015 -1.5 -1.5 1.0 356. NA
>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
Compare the model to the data
draws4 <- as_draws_matrix(draws4)
Ef <- exp(apply(subset(draws4, variable='f'), 2, median))
Ef1 <- apply(subset(draws4, variable='f1'), 2, median)
Ef1 <- exp(Ef1 - mean(Ef1) + mean(log(data$births_relative100)))
Ef2 <- apply(subset(draws4, variable='f2'), 2, median)
Ef2 <- exp(Ef2 - mean(Ef2) + mean(log(data$births_relative100)))
Ef_day_of_week <- apply(subset(draws4, variable='f_day_of_week'), 2, median)
Ef_day_of_week <- exp(Ef_day_of_week - mean(Ef_day_of_week) + mean(log(data$births_relative100)))
Ef3 <- apply(subset(draws4, variable='f3'), 2, median)
Ef3 <- exp(Ef3 - mean(Ef3) + mean(log(data$births_relative100)))
pf <- data %>%
mutate(Ef = Ef) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_line(aes(y=Ef), color=set1[1], alpha=0.75) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births")
pf1 <- data %>%
mutate(Ef1 = Ef1) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_line(aes(y=Ef1), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births")
pf2 <- data %>%
mutate(Ef2 = Ef2) %>%
group_by(day_of_year2) %>%
summarise(meanbirths=mean(births_relative100), meanEf2=mean(Ef2)) %>%
ggplot(aes(x=as.Date("1987-12-31")+day_of_year2, y=meanbirths)) + geom_point(color=set1[2], alpha=0.2) +
scale_x_date(date_breaks = "1 month", date_labels = "%b") +
geom_line(aes(y=meanEf2), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of year")
pf3 <- ggplot(data=data, aes(x=day_of_week, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
scale_x_continuous(breaks = 1:7, labels=c('Mon','Tue','Wed','Thu','Fri','Sat','Sun')) +
geom_line(data=data.frame(x=1:7,y=Ef_day_of_week), aes(x=x, y=Ef_day_of_week), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of week")
pf3b <- data %>%
mutate(Ef3 = Ef3) %>%
ggplot(aes(x=date, y=births_relative100/Ef1/Ef2*100*100)) + geom_point(color=set1[2], alpha=0.2) +
geom_point(aes(y=Ef3), color=set1[1], size=0.1) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births")
(pf + pf1) / (pf2 + pf3b)
<<<<<<< HEAD

=======

>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
The model fits well the different branches visible in plotted daily relative number of births, that is, it is able to model the increasing weekend effect.
Model 5: long term smooth + seasonal + weekday with time dependent magnitude + day of year RHS
The next component to add is day of year effect. Many bank holidays are every year on the same day of year and there might be also other special days that are favored or disfavored.
\[
f = \mbox{intercept} + f_1 + f_2 + \exp(g_3)\beta_{\mbox{day of week}} + \beta_{\mbox{day of year}}\\
\mbox{intercept} \sim \mbox{normal}(0,1)\\
f_1 \sim \mbox{GP}(0,K_1)\\
f_2 \sim \mbox{GP}(0,K_2)\\
g_3 \sim \mbox{GP}(0,K_3)\\
\beta_{\mbox{day of week}} = 0 \quad \mbox{if day of week is Monday}\\
\beta_{\mbox{day of week}} \sim \mbox{normal}(0,1) \quad \mbox{if day of week is not Monday}\\
\beta_{\mbox{day of year}} \sim RHS(0,0.1)
\] As we assume that only some days of year are special, we use regularized horseshoe (RHS) prior for day of year effects.
At this point the optimization didn’t produce reasonable result as earlier and sampling turned out to be very slow. We assumed the optimization fails because there were so many more parameters with hierarchical prior. As even the short chain sampling would have taken more than hour, it would have been time consuming to further to test the model. As part of the quick iterative model building it was better to give up on this model for a moment.
Compile Stan model 5 gpbf5.stan
model5 <- cmdstan_model(stan_file = root("Birthdays", "gpbf5.stan"),
include_paths = root("Birthdays"))
Data to be passed to Stan
standata5 <- list(x=data$id,
y=log(data$births_relative100),
N=length(data$id),
c_f1=1.5, # factor c of basis functions for GP for f1
M_f1=10, # number of basis functions for GP for f1
J_f2=20, # number of basis functions for periodic f2
c_g3=1.5, # factor c of basis functions for GP for g3
M_g3=5, # number of basis functions for GP for g3
scale_global=0.1, # gloval scale for RHS prior
day_of_week=data$day_of_week,
day_of_year=data$day_of_year2) # 1st March = 61 every year
Optimizing is faster than sampling (although this result can be useful in a quick workflow, the result should not be used as the final result).
opt5 <- model5$optimize(data=standata5, init=0, algorithm='lbfgs',
history=100, tol_obj=10)
Check whether parameters have reasonable values
odraws5 <- opt5$draws()
subset(odraws5, variable=c('intercept0','sigma_','lengthscale_','sigma'), regex=TRUE)
<<<<<<< HEAD
# A draws_matrix: 1 draws, and 8 variables
variable
draw intercept0 sigma_f1 sigma_f2 sigma_g3 lengthscale_f1 lengthscale_f2
1 -0.88 0.0039 2.1e-09 0.003 0.021 0.038
variable
draw lengthscale_g3 sigma
1 8.3 0.88
subset(odraws5, variable=c('beta_f3'))
# A draws_matrix: 1 draws, and 6 variables
variable
draw beta_f3[1] beta_f3[2] beta_f3[3] beta_f3[4] beta_f3[5] beta_f3[6]
1 1.7 1.5 1.4 1.5 0.21 -0.25
=======
# A draws_matrix: 1 iterations, 1 chains, and 8 variables
variable
draw intercept0 sigma_f1 sigma_f2 sigma_g3 lengthscale_f1 lengthscale_f2
1 -0.51 0.0099 0.00027 6.3e-07 0.098 0.038
variable
draw lengthscale_g3 sigma
1 5.8 1.4
subset(odraws5, variable=c('beta_f3'))
# A draws_matrix: 1 iterations, 1 chains, and 6 variables
variable
draw beta_f3[1] beta_f3[2] beta_f3[3] beta_f3[4] beta_f3[5] beta_f3[6]
1 1 1.2 1.5 1.2 -0.85 -0.13
>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
Ef4 <- as.numeric(subset(odraws5, variable='beta_f4'))*sd(log(data$births_relative100))
Ef4 <- exp(Ef4)*100
data.frame(x=as.Date("1988-01-01")+0:365, y=Ef4) %>%
ggplot(aes(x=x,y=y)) + geom_line(color=set1[1]) +
scale_x_date(date_breaks = "1 month", date_labels = "%b") +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of year")

Compare the model to the data
Ef <- exp(as.numeric(subset(odraws5, variable='f')))
Ef1 <- as.numeric(subset(odraws5, variable='f1'))
Ef1 <- exp(Ef1 - mean(Ef1) + mean(log(data$births_relative100)))
Ef2 <- as.numeric(subset(odraws5, variable='f2'))
Ef2 <- exp(Ef2 - mean(Ef2) + mean(log(data$births_relative100)))
Ef_day_of_week <- as.numeric(subset(odraws5, variable='f_day_of_week'))
Ef_day_of_week <- exp(Ef_day_of_week - mean(Ef_day_of_week) + mean(log(data$births_relative100)))
Ef4 <- as.numeric(subset(odraws5, variable='beta_f4'))*sd(log(data$births_relative100))
Ef4 <- exp(Ef4)*100
pf <- data %>%
mutate(Ef = Ef) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_line(aes(y=Ef), color=set1[1], alpha=0.75) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births")
pf1 <- data %>%
mutate(Ef1 = Ef1) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_line(aes(y=Ef1), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births")
pf2 <- data %>%
mutate(Ef2 = Ef2) %>%
group_by(day_of_year2) %>%
summarise(meanbirths=mean(births_relative100), meanEf2=mean(Ef2)) %>%
ggplot(aes(x=as.Date("1987-12-31")+day_of_year2, y=meanbirths)) + geom_point(color=set1[2], alpha=0.2) +
scale_x_date(date_breaks = "1 month", date_labels = "%b") +
geom_line(aes(y=meanEf2), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of year")
pf3 <- ggplot(data=data, aes(x=day_of_week, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
scale_x_continuous(breaks = 1:7, labels=c('Mon','Tue','Wed','Thu','Fri','Sat','Sun')) +
geom_line(data=data.frame(x=1:7,y=Ef_day_of_week), aes(x=x, y=Ef_day_of_week), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of week")
pf2b <-data.frame(x=as.Date("1959-12-31")+1:366, y=Ef4) %>%
ggplot(aes(x=x,y=y)) + geom_line(color=set1[1]) +
scale_x_date(date_breaks = "1 month", date_labels = "%b") +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of year")
(pf + pf1) / (pf2 + pf3) / (pf2b)
<<<<<<< HEAD

=======

>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
The quick model fit for model 5 is not good, but as the sampling was very slow it wasn’t easy to figure out what is going wrong.
Model 6: long term smooth + seasonal + weekday + day of year
To simplify the analysis of the day of year effect and make the inference during the exploration faster, we drop the time dependent day of week effect and RHS for a moment and use normal prior for the day of year effect.
\[
f = \mbox{intercept} + f_1 + f_2 + \beta_{\mbox{day of week}} + \beta_{\mbox{day of year}}\\
\mbox{intercept} \sim \mbox{normal}(0,1)\\
f_1 \sim \mbox{GP}(0,K_1)\\
f_2 \sim \mbox{GP}(0,K_2)\\
g_3 \sim \mbox{GP}(0,K_3)\\
\beta_{\mbox{day of week}} = 0 \quad \mbox{if day of week is Monday}\\
\beta_{\mbox{day of week}} \sim \mbox{normal}(0,1) \quad \mbox{if day of week is not Monday}\\
\beta_{\mbox{day of year}} \sim \mbox{normal}(0,0.1)
\]
Compile Stan model 6 gpbf6.stan
model6 <- cmdstan_model(stan_file = root("Birthdays", "gpbf6.stan"),
include_paths = root("Birthdays"))
Data to be passed to Stan
standata6 <- list(x=data$id,
y=log(data$births_relative100),
N=length(data$id),
c_f1=1.5, # factor c of basis functions for GP for f1
M_f1=10, # number of basis functions for GP for f1
J_f2=20, # number of basis functions for periodic f2
day_of_week=data$day_of_week,
day_of_year=data$day_of_year2) # 1st March = 61 every year
Optimizing is faster than sampling (although this result can be useful in a quick workflow, the result should not be used as the final result).
opt6 <- model6$optimize(data=standata6, init=0, algorithm='lbfgs',
history=100, tol_obj=10)
Check whether parameters have reasonable values
odraws6 <- opt6$draws()
subset(odraws6, variable=c('intercept','sigma_','lengthscale_','sigma'), regex=TRUE)
<<<<<<< HEAD
# A draws_matrix: 1 draws, and 7 variables
variable
draw intercept0 sigma_f1 sigma_f2 sigma_f4 lengthscale_f1 lengthscale_f2 sigma
1 0.34 0.54 0.59 0.2 0.15 0.4 0.3
subset(odraws6, variable=c('beta_f3'))
# A draws_matrix: 1 draws, and 6 variables
variable
draw beta_f3[1] beta_f3[2] beta_f3[3] beta_f3[4] beta_f3[5] beta_f3[6]
1 0.34 0.11 0.03 0.16 -1.1 -1.5
=======
# A draws_matrix: 1 iterations, 1 chains, and 7 variables
variable
draw intercept0 sigma_f1 sigma_f2 sigma_f4 lengthscale_f1 lengthscale_f2 sigma
1 0.28 0.7 0.59 0.17 0.23 0.38 0.29
subset(odraws6, variable=c('beta_f3'))
# A draws_matrix: 1 iterations, 1 chains, and 6 variables
variable
draw beta_f3[1] beta_f3[2] beta_f3[3] beta_f3[4] beta_f3[5] beta_f3[6]
1 0.35 0.12 0.041 0.17 -1.1 -1.5
>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
Ef4 <- as.numeric(subset(odraws6, variable='beta_f4'))*sd(log(data$births_relative100))
Ef4 <- exp(Ef4)*100
data.frame(x=as.Date("1988-01-01")+0:365, y=Ef4) %>%
ggplot(aes(x=x,y=y)) + geom_line(color=set1[1]) +
scale_x_date(date_breaks = "1 month", date_labels = "%b") +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of year")
<<<<<<< HEAD

=======

>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
We recognize some familiar structure in the day of year effect and proceed to sampling. Sample short chains using the early stopped optimization result as initial values (although the result from short chains can be useful in a quick workflow, the result should not be used as the final result).
init6 <- sapply(c('intercept0','lengthscale_f1','lengthscale_f2',
'sigma_f1','sigma_f2','sigma_f4','sigma',
'beta_f1','beta_f2','beta_f3','beta_f4'),
function(variable) {as.numeric(subset(odraws6, variable=variable))})
fit6 <- model6$sample(data=standata6, iter_warmup=100, iter_sampling=100,
chains=4, parallel_chains=4,
init=function() { init6 })
Check whether parameters have reasonable values
draws6 <- fit6$draws()
summarise_draws(subset(draws6, variable=c('intercept','sigma_','lengthscale_','sigma'), regex=TRUE))
<<<<<<< HEAD
# A tibble: 7 x 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 intercept0 0.37 0.34 0.39 0.32 -0.17 0.96 1.1 52. 50.
2 sigma_f1 1.5 1.5 0.38 0.32 1.0 2.3 1.0 91. 199.
3 sigma_f2 0.29 0.28 0.052 0.045 0.21 0.37 1.0 82. 196.
4 sigma_f4 0.17 0.17 0.0070 0.0073 0.16 0.18 1.0 320. 294.
5 lengthscale_f1 0.26 0.26 0.097 0.11 0.10 0.41 1.0 106. 43.
6 lengthscale_f2 0.25 0.25 0.027 0.026 0.21 0.30 1.1 58. 175.
7 sigma 0.30 0.30 0.0027 0.0026 0.29 0.30 1.0 408. 283.
summarise_draws(subset(draws6, variable=c('beta_f3')))
# A tibble: 6 x 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 beta_f3[1] 0.35 0.35 0.014 0.014 0.33 0.38 1.0 351. 338.
2 beta_f3[2] 0.13 0.13 0.013 0.013 0.11 0.15 1.0 338. 308.
3 beta_f3[3] 0.046 0.046 0.014 0.013 0.025 0.068 1.0 351. 279.
4 beta_f3[4] 0.18 0.18 0.013 0.013 0.16 0.20 1.0 416. 262.
5 beta_f3[5] -1.1 -1.1 0.013 0.013 -1.1 -1.1 1.0 359. 303.
6 beta_f3[6] -1.5 -1.5 0.014 0.013 -1.5 -1.5 1.0 392. 340.
=======
# A tibble: 7 × 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 intercept0 0.27 0.27 0.013 0.014 0.25 0.30 1.0 174. NA
2 sigma_f1 1.6 1.6 0.31 0.29 1.2 2.2 1.4 9.1 NA
3 sigma_f2 0.25 0.24 0.045 0.037 0.20 0.34 1.5 7.7 NA
4 sigma_f4 0.17 0.17 0.0072 0.0070 0.16 0.18 1.0 469. NA
5 lengthscale_f1 0.29 0.29 0.064 0.060 0.19 0.41 1.1 37. NA
6 lengthscale_f2 0.24 0.23 0.026 0.024 0.19 0.28 1.2 14. NA
7 sigma 0.29 0.29 0.0026 0.0027 0.29 0.30 1.0 256. NA
summarise_draws(subset(draws6, variable=c('beta_f3')))
# A tibble: 6 × 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 beta_f3[1] 0.36 0.36 0.013 0.012 0.33 0.38 1.0 389. NA
2 beta_f3[2] 0.13 0.13 0.014 0.013 0.11 0.15 1.0 363. 295.
3 beta_f3[3] 0.046 0.046 0.014 0.014 0.024 0.068 1.0 590. NA
4 beta_f3[4] 0.18 0.18 0.013 0.013 0.16 0.20 1.0 475. NA
5 beta_f3[5] -1.1 -1.1 0.013 0.013 -1.1 -1.1 1.0 479. NA
6 beta_f3[6] -1.5 -1.5 0.013 0.012 -1.5 -1.5 1.0 410. 340.
>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
draws6 <- as_draws_matrix(draws6)
Ef4 <- apply(subset(draws6, variable='beta_f4'), 2, median)*sd(log(data$births_relative100))
Ef4 <- exp(Ef4)*100
data.frame(x=as.Date("1988-01-01")+0:365, y=Ef4) %>%
ggplot(aes(x=x,y=y)) + geom_line(color=set1[1]) +
scale_x_date(date_breaks = "1 month", date_labels = "%b") +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of year")
<<<<<<< HEAD

=======

>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
Compare the model to the data
draws6 <- as_draws_matrix(draws6)
Ef <- exp(apply(subset(draws6, variable='f'), 2, median))
Ef1 <- apply(subset(draws6, variable='f1'), 2, median)
Ef1 <- exp(Ef1 - mean(Ef1) + mean(log(data$births_relative100)))
Ef2 <- apply(subset(draws6, variable='f2'), 2, median)
Ef2 <- exp(Ef2 - mean(Ef2) + mean(log(data$births_relative100)))
Ef_day_of_week <- apply(subset(draws6, variable='f_day_of_week'), 2, median)
Ef_day_of_week <- exp(Ef_day_of_week - mean(Ef_day_of_week) + mean(log(data$births_relative100)))
Ef4 <- apply(subset(draws6, variable='beta_f4'), 2, median)*sd(log(data$births_relative100))
Ef4 <- exp(Ef4)*100
pf <- data %>%
mutate(Ef = Ef) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_line(aes(y=Ef), color=set1[1], alpha=0.75) +
labs(x="Date", y="Relative number of births")
pf1 <- data %>%
mutate(Ef1 = Ef1) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_line(aes(y=Ef1), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births")
pf2 <- data %>%
mutate(Ef2 = Ef2) %>%
group_by(day_of_year2) %>%
summarise(meanbirths=mean(births_relative100), meanEf2=mean(Ef2)) %>%
ggplot(aes(x=as.Date("1987-12-31")+day_of_year2, y=meanbirths)) + geom_point(color=set1[2], alpha=0.2) +
scale_x_date(date_breaks = "1 month", date_labels = "%b") +
geom_line(aes(y=meanEf2), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of year")
pf3 <- ggplot(data=data, aes(x=day_of_week, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
scale_x_continuous(breaks = 1:7, labels=c('Mon','Tue','Wed','Thu','Fri','Sat','Sun')) +
geom_line(data=data.frame(x=1:7,y=Ef_day_of_week), aes(x=x, y=Ef_day_of_week), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of week")
f13 <- data %>% filter(year==1988)%>%select(day,date)%>%mutate(y=Ef4)%>%filter(day==13)
pf2b <-data.frame(x=as.Date("1988-01-01")+0:365, y=Ef4) %>%
ggplot(aes(x=x,y=y)) + geom_line(color=set1[1]) +
scale_x_date(date_breaks = "1 month", date_labels = "%b") +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of year") +
annotate("text",x=as.Date("1988-01-01"),y=Ef4[1]-1,label="New year") +
annotate("text",x=as.Date("1988-02-14"),y=Ef4[45]+1.5,label="Valentine's day") +
annotate("text",x=as.Date("1988-02-29"),y=Ef4[60]-2.5,label="Leap day") +
annotate("text",x=as.Date("1988-04-01"),y=Ef4[92]-1.5,label="April 1st") +
annotate("text",x=as.Date("1988-07-04"),y=Ef4[186]-1.5,label="Independence day") +
annotate("text",x=as.Date("1988-10-31"),y=Ef4[305]-1.5,label="Halloween") +
annotate("text",x=as.Date("1988-12-24"),y=Ef4[360]-1.5,label="Christmas") +
geom_point(data=f13,aes(x=date,y=y), size=3, shape=1)
(pf + pf1) / (pf2 + pf3) / pf2b
<<<<<<< HEAD

=======

>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
The short sampling result looks reasonable and thus the problem is not in adding the day of year effect itself. In the bottom plot, the circles mark 13th day of each month. Results look similar to our previous analyses , so it seems the day or year effect model component is working as it should, but there was some problem with our RHS implementation. As there is more variation in the day of year effects than we would hope, we did some additional experiments with different priors for the day of year effect (double exponential, Cauchy and Student’s t with unknown degrees of freedom as models 6b, 6c, 6d), but decided it’s better to add other components before investing that part more thoroughly.
Model 7: long term smooth + seasonal + weekday + day of year normal + floating special days
We can see in the model 6 results that day of year effects have some dips in the relative number of births that are spread over a week. From previous analyse we know these correspond to holidays that are not on a specific day of year, but are for example on the last Monday of May. We call these floating special days and include Memorial day (last Monday of May), Labor day (first Monday of September, and we include also the following Tuesday), and Thanksgiving (fourth Thursday of November, and we include also the following Friday).
Compile Stan model 7 gpbf7.stan
model7 <- cmdstan_model(stan_file = root("Birthdays", "gpbf7.stan"),
include_paths = root("Birthdays"))
Floating special days
# Memorial day
memorial_days <- with(data,which(month==5&day_of_week==1&day>=25))
# Labor day
labor_days <- with(data,which(month==9&day_of_week==1&day<=7))
labor_days <- c(labor_days, labor_days+1)
# Thanksgiving
thanksgiving_days <- with(data,which(month==11&day_of_week==4&day>=22&day<=28))
thanksgiving_days <- c(thanksgiving_days, thanksgiving_days+1)
Data to be passed to Stan
standata7 <- list(x=data$id,
y=log(data$births_relative100),
N=length(data$id),
c_f1=1.5, # factor c of basis functions for GP for f1
M_f1=10, # number of basis functions for GP for f1
J_f2=20, # number of basis functions for periodic f2
day_of_week=data$day_of_week,
day_of_year=data$day_of_year2, # 1st March = 61 every year
memorial_days=memorial_days,
labor_days=labor_days,
thanksgiving_days=thanksgiving_days)
Optimizing is faster than sampling (although this result can be useful in a quick workflow, the result should not be used as the final result).
opt7 <- model7$optimize(data=standata7, init=0, algorithm='lbfgs',
history=100, tol_obj=10)
Check whether parameters have reasonable values
odraws7 <- opt7$draws()
subset(odraws7, variable=c('intercept','sigma_','lengthscale_','sigma'), regex=TRUE)
<<<<<<< HEAD
# A draws_matrix: 1 draws, and 7 variables
variable
draw intercept0 sigma_f1 sigma_f2 sigma_f4 lengthscale_f1 lengthscale_f2 sigma
1 0.23 0.64 0.66 0.16 0.17 0.28 0.27
subset(odraws7, variable=c('beta_f3'))
# A draws_matrix: 1 draws, and 6 variables
variable
draw beta_f3[1] beta_f3[2] beta_f3[3] beta_f3[4] beta_f3[5] beta_f3[6]
1 0.31 0.073 0.025 0.15 -1.2 -1.6
=======
# A draws_matrix: 1 iterations, 1 chains, and 7 variables
variable
draw intercept0 sigma_f1 sigma_f2 sigma_f4 lengthscale_f1 lengthscale_f2 sigma
1 0.35 0.5 0.54 0.18 0.19 0.45 0.28
subset(odraws7, variable=c('beta_f3'))
# A draws_matrix: 1 iterations, 1 chains, and 6 variables
variable
draw beta_f3[1] beta_f3[2] beta_f3[3] beta_f3[4] beta_f3[5] beta_f3[6]
1 0.27 0.038 -0.0033 0.11 -1.2 -1.6
>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
Ef4 <- as.numeric(subset(odraws7, variable='beta_f4'))*sd(log(data$births_relative100))
Ef4 <- exp(Ef4)*100
data.frame(x=as.Date("1988-01-01")+0:365, y=Ef4) %>%
ggplot(aes(x=x,y=y)) + geom_line(color=set1[1]) +
scale_x_date(date_breaks = "1 month", date_labels = "%b") +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of year")
<<<<<<< HEAD

=======

>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
Sample short chains using the early stopped optimization result as initial values (although the result from short chains can be useful in a quick workflow, the result should not be used as the final result).
init7 <- sapply(c('intercept0','lengthscale_f1','lengthscale_f2',
'sigma_f1','sigma_f2','sigma_f4','sigma',
'beta_f1','beta_f2','beta_f3','beta_f4','beta_f5'),
function(variable) {as.numeric(subset(odraws7, variable=variable))})
fit7 <- model7$sample(data=standata7, iter_warmup=100, iter_sampling=100, chains=4, parallel_chains=4,
init=function() { init7 }, refresh=10)
Check whether parameters have reasonable values
draws7 <- fit7$draws()
summarise_draws(subset(draws7, variable=c('intercept','sigma_','lengthscale_','sigma'), regex=TRUE))
<<<<<<< HEAD
# A tibble: 7 x 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 intercept0 0.37 0.36 0.47 0.43 -0.37 1.1 1.0 136. 106.
2 sigma_f1 1.5 1.5 0.39 0.34 0.97 2.2 1.0 98. 70.
3 sigma_f2 0.29 0.27 0.061 0.055 0.21 0.40 1.0 157. 167.
4 sigma_f4 0.17 0.17 0.0072 0.0071 0.16 0.18 1.0 340. 362.
5 lengthscale_f1 0.25 0.25 0.10 0.11 0.084 0.43 1.0 171. 170.
6 lengthscale_f2 0.30 0.30 0.042 0.040 0.24 0.37 1.0 76. 164.
7 sigma 0.27 0.27 0.0022 0.0024 0.27 0.28 1.0 374. 311.
summarise_draws(subset(draws7, variable=c('beta_f3')))
# A tibble: 6 x 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 beta_f3[1] 0.30 0.30 0.013 0.012 0.28 0.33 1.0 430. 331.
2 beta_f3[2] 0.073 0.073 0.012 0.011 0.053 0.095 1.0 397. 313.
3 beta_f3[3] 0.029 0.030 0.012 0.011 0.0092 0.050 1.0 389. 196.
4 beta_f3[4] 0.14 0.14 0.013 0.011 0.12 0.16 1.0 428. 258.
5 beta_f3[5] -1.2 -1.2 0.013 0.012 -1.2 -1.1 1.0 421. 258.
6 beta_f3[6] -1.6 -1.6 0.012 0.011 -1.6 -1.6 1.0 379. 299.
=======
# A tibble: 7 × 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 intercept0 0.33 0.33 0.012 0.012 0.31 0.35 1.1 83. NA
2 sigma_f1 1.4 1.4 0.28 0.21 1.0 2.1 1.4 9.1 NA
3 sigma_f2 0.29 0.29 0.040 0.036 0.23 0.36 1.2 24. NA
4 sigma_f4 0.17 0.17 0.0072 0.0072 0.16 0.18 1.0 383. NA
5 lengthscale_f1 0.26 0.25 0.073 0.057 0.16 0.40 1.6 7.1 NA
6 lengthscale_f2 0.30 0.30 0.032 0.032 0.24 0.35 1.3 10. NA
7 sigma 0.27 0.27 0.0024 0.0026 0.27 0.28 1.0 432. NA
summarise_draws(subset(draws7, variable=c('beta_f3')))
# A tibble: 6 × 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 beta_f3[1] 0.30 0.30 0.012 0.012 0.28 0.32 1.0 442. NA
2 beta_f3[2] 0.073 0.074 0.012 0.013 0.052 0.093 1.0 549. NA
3 beta_f3[3] 0.029 0.028 0.012 0.013 0.0095 0.049 1.0 461. 345.
4 beta_f3[4] 0.14 0.14 0.012 0.012 0.12 0.16 1.0 468. NA
5 beta_f3[5] -1.2 -1.2 0.012 0.012 -1.2 -1.1 1.0 527. NA
6 beta_f3[6] -1.6 -1.6 0.012 0.012 -1.6 -1.6 1.0 448. 362.
>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
Compare the model to the data
draws7 <- as_draws_matrix(draws7)
Ef <- exp(apply(subset(draws7, variable='f'), 2, median))
Ef1 <- apply(subset(draws7, variable='f1'), 2, median)
Ef1 <- exp(Ef1 - mean(Ef1) + mean(log(data$births_relative100)))
Ef2 <- apply(subset(draws7, variable='f2'), 2, median)
Ef2 <- exp(Ef2 - mean(Ef2) + mean(log(data$births_relative100)))
Ef_day_of_week <- apply(subset(draws7, variable='f_day_of_week'), 2, median)
Ef_day_of_week <- exp(Ef_day_of_week - mean(Ef_day_of_week) + mean(log(data$births_relative100)))
Ef4 <- apply(subset(draws7, variable='beta_f4'), 2, median)*sd(log(data$births_relative100))
Ef4 <- exp(Ef4)*100
Efloats <- apply(subset(draws7, variable='beta_f5'), 2, median)*sd(log(data$births_relative100))
Efloats <- exp(Efloats)*100
floats1988<-c(memorial_days[20], labor_days[c(20,40)], thanksgiving_days[c(20,40)])-6939
Ef4float <- Ef4
Ef4float[floats1988] <- Ef4float[floats1988]*Efloats[c(1,2,2,3,3)]/100
pf <- data %>%
mutate(Ef = Ef) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_line(aes(y=Ef), color=set1[1], alpha=0.75) +
labs(x="Date", y="Relative number of births")
pf1 <- data %>%
mutate(Ef1 = Ef1) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_line(aes(y=Ef1), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births")
pf2 <- data %>%
mutate(Ef2 = Ef2) %>%
group_by(day_of_year2) %>%
summarise(meanbirths=mean(births_relative100), meanEf2=mean(Ef2)) %>%
ggplot(aes(x=as.Date("1987-12-31")+day_of_year2, y=meanbirths)) + geom_point(color=set1[2], alpha=0.2) +
scale_x_date(date_breaks = "1 month", date_labels = "%b") +
geom_line(aes(y=meanEf2), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of year")
pf3 <- ggplot(data=data, aes(x=day_of_week, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
scale_x_continuous(breaks = 1:7, labels=c('Mon','Tue','Wed','Thu','Fri','Sat','Sun')) +
geom_line(data=data.frame(x=1:7,y=Ef_day_of_week), aes(x=x, y=Ef_day_of_week), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of week")
f13 <- data %>% filter(year==1988)%>%select(day,date)%>%mutate(y=Ef4float)%>%filter(day==13)
pf2b <-data.frame(x=as.Date("1988-01-01")+0:365, y=Ef4float) %>%
ggplot(aes(x=x,y=y)) + geom_line(color=set1[1]) +
scale_x_date(date_breaks = "1 month", date_labels = "%b") +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of year") +
annotate("text",x=as.Date("1988-01-01"),y=Ef4float[1]-1,label="New year") +
annotate("text",x=as.Date("1988-02-14"),y=Ef4float[45]+1.5,label="Valentine's day") +
annotate("text",x=as.Date("1988-02-29"),y=Ef4float[60]-2.5,label="Leap day") +
annotate("text",x=as.Date("1988-04-01"),y=Ef4float[92]-1.5,label="April 1st") +
annotate("text",x=as.Date("1988-07-04"),y=Ef4float[186]-1.5,label="Independence day") +
annotate("text",x=as.Date("1988-10-31"),y=Ef4float[305]-1.5,label="Halloween") +
annotate("text",x=as.Date("1988-12-24"),y=Ef4float[360]-2,label="Christmas") +
annotate("text",x=as.Date("1988-05-30"),y=Ef4float[151]-1.5,label="Memorial day") +
annotate("text",x=as.Date("1988-09-05"),y=Ef4float[249]-1.5,label="Labor day") +
annotate("text",x=as.Date("1988-11-24"),y=Ef4float[329]-1,label="Thanksgiving")+
geom_point(data=f13,aes(x=date,y=y), size=3, shape=1)
(pf + pf1) / (pf2 + pf3) / (pf2b)
<<<<<<< HEAD

=======

>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
The day of year and floating special day effects are shown for year 1988 (which is also a leap year) and the results seem reasonable.
Model 8: long term smooth + seasonal + weekday with time dependent magnitude + day of year + special
As the day of year and floating day effects work well, we’ll add the time dependent day of week effect back to the model.
Compile Stan model 8 gpbf8.stan
model8 <- cmdstan_model(stan_file = root("Birthdays", "gpbf8.stan"),
include_paths = root("Birthdays"))
Floating special days
# Memorial day
memorial_days <- with(data,which(month==5&day_of_week==1&day>=25))
# Labor day
labor_days <- with(data,which(month==9&day_of_week==1&day<=7))
labor_days <- c(labor_days, labor_days+1)
# Thanksgiving
thanksgiving_days <- with(data,which(month==11&day_of_week==4&day>=22&day<=28))
thanksgiving_days <- c(thanksgiving_days, thanksgiving_days+1)
Data to be passed to Stan
standata8 <- list(x=data$id,
y=log(data$births_relative100),
N=length(data$id),
c_f1=1.5, # factor c of basis functions for GP for f1
M_f1=10, # number of basis functions for GP for f1
J_f2=20, # number of basis functions for periodic f2
c_g3=1.5, # factor c of basis functions for GP for g3
M_g3=5, # number of basis functions for GP for g3
day_of_week=data$day_of_week,
day_of_year=data$day_of_year2, # 1st March = 61 every year
memorial_days=memorial_days,
labor_days=labor_days,
thanksgiving_days=thanksgiving_days)
Optimizing is faster than sampling (although this result can be useful in a quick workflow, the result should not be used as the final result).
opt8 <- model8$optimize(data=standata8, init=0.1, algorithm='lbfgs',
history=100, tol_obj=10)
Check whether parameters have reasonable values
odraws8 <- opt8$draws()
subset(odraws8, variable=c('intercept','sigma_','lengthscale_','sigma'), regex=TRUE)
<<<<<<< HEAD
# A draws_matrix: 1 draws, and 9 variables
variable
draw intercept0 sigma_f1 sigma_f2 sigma_g3 sigma_f4 lengthscale_f1
1 0.25 0.48 0.69 0.3 0.18 0.19
variable
draw lengthscale_f2 lengthscale_g3
1 0.26 0.7
# ... with 1 more variables
subset(odraws8, variable=c('beta_f3'))
# A draws_matrix: 1 draws, and 6 variables
variable
draw beta_f3[1] beta_f3[2] beta_f3[3] beta_f3[4] beta_f3[5] beta_f3[6]
1 0.33 0.071 0.031 0.15 -1.4 -1.8
=======
# A draws_matrix: 1 iterations, 1 chains, and 9 variables
variable
draw intercept0 sigma_f1 sigma_f2 sigma_g3 sigma_f4 lengthscale_f1
1 0.33 1 0.64 0.34 0.16 0.21
variable
draw lengthscale_f2 lengthscale_g3
1 0.39 0.72
# ... with 1 more variables
subset(odraws8, variable=c('beta_f3'))
# A draws_matrix: 1 iterations, 1 chains, and 6 variables
variable
draw beta_f3[1] beta_f3[2] beta_f3[3] beta_f3[4] beta_f3[5] beta_f3[6]
1 0.29 0.066 0.032 0.13 -1.2 -1.6
>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
Ef4 <- as.numeric(subset(odraws8, variable='beta_f4'))*sd(log(data$births_relative100))
Ef4 <- exp(Ef4)*100
data.frame(x=as.Date("1988-01-01")+0:365, y=Ef4) %>%
ggplot(aes(x=x,y=y)) + geom_line(color=set1[1]) +
scale_x_date(date_breaks = "1 month", date_labels = "%b") +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of year")
<<<<<<< HEAD

=======

>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
Compare the model to the data
Ef <- exp(as.numeric(subset(odraws8, variable='f')))
Ef1 <- as.numeric(subset(odraws8, variable='f1'))
Ef1 <- exp(Ef1 - mean(Ef1) + mean(log(data$births_relative100)))
Ef2 <- as.numeric(subset(odraws8, variable='f2'))
Ef2 <- exp(Ef2 - mean(Ef2) + mean(log(data$births_relative100)))
Ef_day_of_week <- as.numeric(subset(odraws8, variable='f_day_of_week'))
Ef_day_of_week <- exp(Ef_day_of_week - mean(Ef_day_of_week) + mean(log(data$births_relative100)))
Ef3 <- as.numeric(subset(odraws8, variable='f3'))
Ef3 <- exp(Ef3 - mean(Ef3) + mean(log(data$births_relative100)))
Ef4 <- as.numeric(subset(odraws8, variable='beta_f4'))*sd(log(data$births_relative100))
Ef4 <- exp(Ef4)*100
Efloats <- as.numeric(subset(odraws8, variable='beta_f5'))*sd(log(data$births_relative100))
Efloats <- exp(Efloats)*100
floats1988<-c(memorial_days[20], labor_days[c(20,40)], thanksgiving_days[c(20,40)])-6939
Ef4float <- Ef4
Ef4float[floats1988] <- Ef4float[floats1988]*Efloats[c(1,2,2,3,3)]/100
pf <- data %>%
mutate(Ef = Ef) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_point(aes(y=Ef), color=set1[1], alpha=0.2) +
labs(x="Date", y="Relative number of births")
pf1 <- data %>%
mutate(Ef1 = Ef1) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_line(aes(y=Ef1), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births")
pf2 <- data %>%
mutate(Ef2 = Ef2) %>%
group_by(day_of_year2) %>%
summarise(meanbirths=mean(births_relative100), meanEf2=mean(Ef2)) %>%
ggplot(aes(x=as.Date("1987-12-31")+day_of_year2, y=meanbirths)) + geom_point(color=set1[2], alpha=0.2) +
scale_x_date(date_breaks = "1 month", date_labels = "%b") +
geom_line(aes(y=meanEf2), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of year")
pf3 <- ggplot(data=data, aes(x=day_of_week, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
scale_x_continuous(breaks = 1:7, labels=c('Mon','Tue','Wed','Thu','Fri','Sat','Sun')) +
geom_line(data=data.frame(x=1:7,y=Ef_day_of_week), aes(x=x, y=Ef_day_of_week), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of week")
N=length(data$id)
pf3b <- data %>%
mutate(Ef3 = Ef3*Ef1/100) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_point(aes(y=Ef3), color=set1[1], size=0.1) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births") +
annotate("text",x=as.Date("1989-08-01"),y=(Ef3*Ef1/100)[c((N-5):(N-4), N, N-6)],label=c("Mon","Tue","Sat","Sun"))
f13 <- data %>% filter(year==1988)%>%select(day,date)%>%mutate(y=Ef4float)%>%filter(day==13)
pf2b <-data.frame(x=as.Date("1988-01-01")+0:365, y=Ef4float) %>%
ggplot(aes(x=x,y=y)) + geom_line(color=set1[1]) +
scale_x_date(date_breaks = "1 month", date_labels = "%b") +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of year") +
annotate("text",x=as.Date("1988-01-01"),y=Ef4float[1]-1,label="New year") +
annotate("text",x=as.Date("1988-02-14"),y=Ef4float[45]+1.5,label="Valentine's day") +
annotate("text",x=as.Date("1988-02-29"),y=Ef4float[60]-2.5,label="Leap day") +
annotate("text",x=as.Date("1988-04-01"),y=Ef4float[92]-1.5,label="April 1st") +
annotate("text",x=as.Date("1988-07-04"),y=Ef4float[186]-1.5,label="Independence day") +
annotate("text",x=as.Date("1988-10-31"),y=Ef4float[305]-1.5,label="Halloween") +
annotate("text",x=as.Date("1988-12-24"),y=Ef4float[360]-2,label="Christmas") +
annotate("text",x=as.Date("1988-05-30"),y=Ef4float[151]-2,label="Memorial day") +
annotate("text",x=as.Date("1988-09-05"),y=Ef4float[249]-1.5,label="Labor day") +
annotate("text",x=as.Date("1988-11-24"),y=Ef4float[329]-1,label="Thanksgiving")+
geom_point(data=f13,aes(x=date,y=y), size=3, shape=1)
(pf + pf1) / (pf2 + pf3b) / (pf2b)
<<<<<<< HEAD

=======

>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
Sample short chains using the early stopped optimization result as initial values (although the result from short chains can be useful in a quick workflow, the result should not be used as the final result).
init8 <- sapply(c('intercept0','lengthscale_f1','lengthscale_f2','lengthscale_g3',
'sigma_f1','sigma_f2','sigma_g3','sigma_f4','sigma',
'beta_f1','beta_f2','beta_f3','beta_g3','beta_f4','beta_f5'),
function(variable) {as.numeric(subset(odraws8, variable=variable))})
fit8 <- model8$sample(data=standata8, iter_warmup=100, iter_sampling=100, chains=4, parallel_chains=4,
init=function() { init8 }, refresh=10)
Check whether parameters have reasonable values
draws8 <- fit8$draws()
summarise_draws(subset(draws8, variable=c('intercept','sigma_','lengthscale_','sigma'), regex=TRUE))
<<<<<<< HEAD
# A tibble: 9 x 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 intercept0 0.48 0.47 0.46 0.46 -0.26 1.2 1.1 93. 97.
2 sigma_f1 1.5 1.5 0.33 0.31 1.0 2.1 1.0 80. 90.
3 sigma_f2 0.29 0.28 0.061 0.058 0.21 0.40 1.1 32. 203.
4 sigma_g3 0.19 0.18 0.047 0.037 0.13 0.28 1.0 134. 164.
5 sigma_f4 0.17 0.17 0.0070 0.0070 0.16 0.18 1.0 372. 277.
6 lengthscale_f1 0.27 0.28 0.095 0.094 0.11 0.43 1.0 138. 120.
7 lengthscale_f2 0.30 0.30 0.039 0.038 0.24 0.36 1.0 77. 172.
8 lengthscale_g3 0.73 0.75 0.18 0.20 0.43 0.99 1.0 130. 154.
9 sigma 0.25 0.25 0.0022 0.0022 0.24 0.25 1.0 422. 277.
summarise_draws(subset(draws8, variable=c('beta_f3')))
# A tibble: 6 x 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 beta_f3[1] 0.30 0.29 0.035 0.033 0.24 0.36 1.1 50. 44.
2 beta_f3[2] 0.079 0.078 0.015 0.014 0.058 0.10 1.0 145. 198.
3 beta_f3[3] 0.042 0.040 0.012 0.012 0.024 0.063 1.0 314. 336.
4 beta_f3[4] 0.14 0.14 0.020 0.020 0.11 0.17 1.0 81. 78.
5 beta_f3[5] -1.1 -1.1 0.12 0.11 -1.4 -0.95 1.1 34. 44.
6 beta_f3[6] -1.5 -1.5 0.17 0.15 -1.8 -1.3 1.1 36. 44.
=======
# A tibble: 9 × 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 intercept0 0.32 0.32 0.012 0.012 0.30 0.34 1.0 223. NA
2 sigma_f1 1.6 1.6 0.34 0.35 1.1 2.2 1.0 110. NA
3 sigma_f2 0.28 0.28 0.047 0.044 0.22 0.36 1.0 225. NA
4 sigma_g3 0.20 0.19 0.047 0.040 0.14 0.29 1.1 145. NA
5 sigma_f4 0.17 0.17 0.0069 0.0069 0.16 0.18 1.0 424. 385.
6 lengthscale_f1 0.28 0.28 0.11 0.12 0.087 0.45 1.0 87. NA
7 lengthscale_f2 0.30 0.30 0.037 0.036 0.24 0.36 1.0 91. NA
8 lengthscale_g3 0.73 0.74 0.19 0.18 0.38 1.0 1.0 126. NA
9 sigma 0.25 0.25 0.0020 0.0020 0.24 0.25 1.0 383. 338.
summarise_draws(subset(draws8, variable=c('beta_f3')))
# A tibble: 6 × 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 beta_f3[1] 0.30 0.30 0.011 0.011 0.28 0.31 1.0 444. NA
2 beta_f3[2] 0.080 0.080 0.010 0.011 0.063 0.097 1.0 423. NA
3 beta_f3[3] 0.042 0.041 0.0099 0.0099 0.026 0.058 1.0 429. NA
4 beta_f3[4] 0.14 0.14 0.011 0.011 0.13 0.16 1.0 423. NA
5 beta_f3[5] -1.1 -1.1 0.011 0.010 -1.2 -1.1 1.0 409. NA
6 beta_f3[6] -1.5 -1.5 0.011 0.012 -1.6 -1.5 1.0 417. 281.
>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
Compare the model to the data
draws8 <- as_draws_matrix(draws8)
Ef <- exp(apply(subset(draws8, variable='f'), 2, median))
Ef1 <- apply(subset(draws8, variable='f1'), 2, median)
Ef1 <- exp(Ef1 - mean(Ef1) + mean(log(data$births_relative100)))
Ef2 <- apply(subset(draws8, variable='f2'), 2, median)
Ef2 <- exp(Ef2 - mean(Ef2) + mean(log(data$births_relative100)))
Ef_day_of_week <- apply(subset(draws8, variable='f_day_of_week'), 2, median)
Ef_day_of_week <- exp(Ef_day_of_week - mean(Ef_day_of_week) + mean(log(data$births_relative100)))
Ef3 <- apply(subset(draws8, variable='f3'), 2, median)
Ef3 <- exp(Ef3 - mean(Ef3) + mean(log(data$births_relative100)))
Ef4 <- apply(subset(draws8, variable='beta_f4'), 2, median)*sd(log(data$births_relative100))
Ef4 <- exp(Ef4)*100
Efloats <- apply(subset(draws8, variable='beta_f5'), 2, median)*sd(log(data$births_relative100))
Efloats <- exp(Efloats)*100
floats1988<-c(memorial_days[20], labor_days[c(20,40)], thanksgiving_days[c(20,40)])-6939
Ef4float <- Ef4
Ef4float[floats1988] <- Ef4float[floats1988]*Efloats[c(1,2,2,3,3)]/100
pf <- data %>%
mutate(Ef = Ef) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_point(aes(y=Ef), color=set1[1], alpha=0.2) +
labs(x="Date", y="Relative number of births")
pf1 <- data %>%
mutate(Ef1 = Ef1) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_line(aes(y=Ef1), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births")
pf2 <- data %>%
mutate(Ef2 = Ef2) %>%
group_by(day_of_year2) %>%
summarise(meanbirths=mean(births_relative100), meanEf2=mean(Ef2)) %>%
ggplot(aes(x=as.Date("1987-12-31")+day_of_year2, y=meanbirths)) + geom_point(color=set1[2], alpha=0.2) +
scale_x_date(date_breaks = "1 month", date_labels = "%b") +
geom_line(aes(y=meanEf2), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of year")
pf3 <- ggplot(data=data, aes(x=day_of_week, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
scale_x_continuous(breaks = 1:7, labels=c('Mon','Tue','Wed','Thu','Fri','Sat','Sun')) +
geom_line(data=data.frame(x=1:7,y=Ef_day_of_week), aes(x=x, y=Ef_day_of_week), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of week")
N=length(data$id)
pf3b <- data %>%
mutate(Ef3 = Ef3*Ef1/100) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_point(aes(y=Ef3), color=set1[1], size=0.1) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births") +
annotate("text",x=as.Date("1989-08-01"),y=(Ef3*Ef1/100)[c((N-5):(N-4), N, N-6)],label=c("Mon","Tue","Sat","Sun"))
f13 <- data %>% filter(year==1988)%>%select(day,date)%>%mutate(y=Ef4float)%>%filter(day==13)
pf2b <-data.frame(x=as.Date("1988-01-01")+0:365, y=Ef4float) %>%
ggplot(aes(x=x,y=y)) + geom_line(color=set1[1]) +
scale_x_date(date_breaks = "1 month", date_labels = "%b") +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of year") +
annotate("text",x=as.Date("1988-01-01"),y=Ef4float[1]-1,label="New year") +
annotate("text",x=as.Date("1988-02-14"),y=Ef4float[45]+1.5,label="Valentine's day") +
annotate("text",x=as.Date("1988-02-29"),y=Ef4float[60]-2.5,label="Leap day") +
annotate("text",x=as.Date("1988-04-01"),y=Ef4float[92]-1.5,label="April 1st") +
annotate("text",x=as.Date("1988-07-04"),y=Ef4float[186]-1.5,label="Independence day") +
annotate("text",x=as.Date("1988-10-31"),y=Ef4float[305]-1.5,label="Halloween") +
annotate("text",x=as.Date("1988-12-24"),y=Ef4float[360]-2,label="Christmas") +
annotate("text",x=as.Date("1988-05-30"),y=Ef4float[151]-2,label="Memorial day") +
annotate("text",x=as.Date("1988-09-05"),y=Ef4float[249]-1.5,label="Labor day") +
annotate("text",x=as.Date("1988-11-24"),y=Ef4float[329]-1,label="Thanksgiving")+
geom_point(data=f13,aes(x=date,y=y), size=3, shape=1)
(pf + pf1) / (pf2 + pf3b) / (pf2b)
<<<<<<< HEAD

=======

>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
The inference for the model works fine, which hints that our RHS implementation for the model 5 was wrong or had very difficult posterior. Before testing RHS again, we’ll test with an easier to implement Student’s \(t\) prior whether long tailed prior for day of year effect is reasonable. These experiments help also to find out whether the day of year effect is sensitive to the prior choice.
Model 8+t_nu: day of year effect with Student’s t prior
Compile Stan model 8 + t_nu gpbf8tnu.stan
model8tnu <- cmdstan_model(stan_file = root("Birthdays", "gpbf8tnu.stan"),
include_paths = root("Birthdays"))
Optimizing is faster than sampling (although this result can be useful in a quick workflow, the result should not be used as the final result).
opt8tnu <- model8tnu$optimize(data=standata8, init=0.1, algorithm='lbfgs',
history=100, tol_obj=10)
odraws8tnu <- opt8tnu$draws()
Sample short chains using the early stopped optimization result as initial values (although the result from short chains can be useful in a quick workflow, the result should not be used as the final result).
init8tnu <- sapply(c('intercept0','lengthscale_f1','lengthscale_f2','lengthscale_g3',
'sigma_f1','sigma_f2','sigma_g3','sigma_f4','nu_f4','sigma',
'beta_f1','beta_f2','beta_f3','beta_g3','beta_f4','beta_f5'),
function(variable) {as.numeric(subset(odraws8tnu, variable=variable))})
fit8tnu <- model8tnu$sample(data=standata8, iter_warmup=100, iter_sampling=100,
chains=4, parallel_chains=4,
init=function() { init8tnu }, refresh=10)
Check whether parameters have reasonable values
draws8tnu <- fit8tnu$draws()
summarise_draws(subset(draws8tnu, variable=c('intercept','sigma_','lengthscale_','sigma','nu_'), regex=TRUE))
<<<<<<< HEAD
# A tibble: 10 x 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 intercept0 0.46 0.49 0.52 0.49 -0.41 1.3 1.1 42. 49.
2 sigma_f1 1.6 1.5 0.37 0.31 1.2 2.3 1.0 188. 191.
3 sigma_f2 0.27 0.27 0.041 0.042 0.21 0.34 1.1 97. 168.
4 sigma_g3 0.19 0.18 0.046 0.043 0.13 0.27 1.0 185. 174.
5 sigma_f4 0.0082 0.0080 0.0019 0.0019 0.0053 0.012 1.6 7.9 51.
6 lengthscal… 0.27 0.27 0.10 0.11 0.087 0.43 1.0 93. 159.
7 lengthscal… 0.21 0.21 0.016 0.015 0.18 0.23 1.0 132. 176.
8 lengthscal… 0.73 0.72 0.20 0.22 0.38 1.0 1.0 206. 262.
9 sigma 0.24 0.24 0.0021 0.0022 0.24 0.25 1.0 415. 272.
10 nu_f4 1.1 1.0 0.065 0.046 1.0 1.2 1.1 42. 90.
=======
# A tibble: 10 × 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 intercept0 0.35 0.35 0.0078 0.0083 0.33 0.36 1.0 431. NA
2 sigma_f1 1.6 1.5 0.33 0.32 1.1 2.1 1.0 173. NA
3 sigma_f2 0.28 0.27 0.050 0.044 0.22 0.37 1.0 69. NA
4 sigma_g3 0.20 0.19 0.050 0.048 0.13 0.29 1.0 263. NA
5 sigma_f4 0.0085 0.0080 0.0027 0.0028 0.0049 0.013 1.6 7.0 NA
6 lengthscale_f1 0.26 0.25 0.093 0.10 0.11 0.42 1.0 106. NA
7 lengthscale_f2 0.21 0.21 0.015 0.015 0.18 0.23 1.0 137. NA
8 lengthscale_g3 0.77 0.77 0.19 0.18 0.45 1.1 1.0 212. NA
9 sigma 0.24 0.24 0.0020 0.0021 0.24 0.25 1.0 343. NA
10 nu_f4 1.1 1.0 0.063 0.044 1.0 1.2 1.2 14. NA
>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
Posterior of degrees of freedom nu_f4 is very close to 1, and thus the distribution is very close to Cauchy. This is strong evidence that the distribution of day of year effects is far from normal, even if Cauchy would not be the correct distribution. Compare the model to the data
draws8 <- as_draws_matrix(draws8tnu)
Ef <- exp(apply(subset(draws8, variable='f'), 2, median))
Ef1 <- apply(subset(draws8, variable='f1'), 2, median)
Ef1 <- exp(Ef1 - mean(Ef1) + mean(log(data$births_relative100)))
Ef2 <- apply(subset(draws8, variable='f2'), 2, median)
Ef2 <- exp(Ef2 - mean(Ef2) + mean(log(data$births_relative100)))
Ef_day_of_week <- apply(subset(draws8, variable='f_day_of_week'), 2, median)
Ef_day_of_week <- exp(Ef_day_of_week - mean(Ef_day_of_week) + mean(log(data$births_relative100)))
Ef3 <- apply(subset(draws8, variable='f3'), 2, median)
Ef3 <- exp(Ef3 - mean(Ef3) + mean(log(data$births_relative100)))
Ef4 <- apply(subset(draws8, variable='beta_f4'), 2, median)*sd(log(data$births_relative100))
Ef4 <- exp(Ef4)*100
Efloats <- apply(subset(draws8, variable='beta_f5'), 2, median)*sd(log(data$births_relative100))
Efloats <- exp(Efloats)*100
floats1988<-c(memorial_days[20], labor_days[c(20,40)], thanksgiving_days[c(20,40)])-6939
Ef4float <- Ef4
Ef4float[floats1988] <- Ef4float[floats1988]*Efloats[c(1,2,2,3,3)]/100
pf <- data %>%
mutate(Ef = Ef) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_point(aes(y=Ef), color=set1[1], alpha=0.2) +
labs(x="Date", y="Relative number of births")
pf1 <- data %>%
mutate(Ef1 = Ef1) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_line(aes(y=Ef1), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births")
pf2 <- data %>%
mutate(Ef2 = Ef2) %>%
group_by(day_of_year2) %>%
summarise(meanbirths=mean(births_relative100), meanEf2=mean(Ef2)) %>%
ggplot(aes(x=as.Date("1987-12-31")+day_of_year2, y=meanbirths)) + geom_point(color=set1[2], alpha=0.2) +
scale_x_date(date_breaks = "1 month", date_labels = "%b") +
geom_line(aes(y=meanEf2), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of year")
pf3 <- ggplot(data=data, aes(x=day_of_week, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
scale_x_continuous(breaks = 1:7, labels=c('Mon','Tue','Wed','Thu','Fri','Sat','Sun')) +
geom_line(data=data.frame(x=1:7,y=Ef_day_of_week), aes(x=x, y=Ef_day_of_week), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of week")
N=length(data$id)
pf3b <- data %>%
mutate(Ef3 = Ef3*Ef1/100) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_point(aes(y=Ef3), color=set1[1], size=0.1) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births") +
annotate("text",x=as.Date("1989-08-01"),y=(Ef3*Ef1/100)[c((N-5):(N-4), N, N-6)],label=c("Mon","Tue","Sat","Sun"))
f13 <- data %>% filter(year==1988)%>%select(day,date)%>%mutate(y=Ef4float)%>%filter(day==13)
pf2b <-data.frame(x=as.Date("1988-01-01")+0:365, y=Ef4float) %>%
ggplot(aes(x=x,y=y)) + geom_line(color=set1[1]) +
scale_x_date(date_breaks = "1 month", date_labels = "%b") +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of year") +
annotate("text",x=as.Date("1988-01-01"),y=Ef4float[1]-1,label="New year") +
annotate("text",x=as.Date("1988-02-14"),y=Ef4float[45]+1.5,label="Valentine's day") +
annotate("text",x=as.Date("1988-02-29"),y=Ef4float[60]-2.5,label="Leap day") +
annotate("text",x=as.Date("1988-04-01"),y=Ef4float[92]-1.5,label="April 1st") +
annotate("text",x=as.Date("1988-07-04"),y=Ef4float[186]-1.5,label="Independence day") +
annotate("text",x=as.Date("1988-10-31"),y=Ef4float[305]-1.5,label="Halloween") +
annotate("text",x=as.Date("1988-12-24"),y=Ef4float[360]-2,label="Christmas") +
annotate("text",x=as.Date("1988-05-30"),y=Ef4float[151]-2,label="Memorial day") +
annotate("text",x=as.Date("1988-09-05"),y=Ef4float[249]-1.5,label="Labor day") +
annotate("text",x=as.Date("1988-11-24"),y=Ef4float[329]-1,label="Thanksgiving")+
geom_point(data=f13,aes(x=date,y=y), size=3, shape=1)
(pf + pf1) / (pf2 + pf3b) / (pf2b)
<<<<<<< HEAD

=======

>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
The other effects seem to be quite similar as with the previous model, but the day of year effects are clearly different with most days having non-detectable effect. There are also effects that seemed to be quite clear in normal prior model such as 13th day of month effect, which is not visible anymore. As the posterior of degrees of freedom t_nu was concentrated close to 1, it’s likely that the normal prior for day of year effect can’t be the best. So far we hadn’t used model comparison such as leave-one-out cross-validation (LOO-CV) as each added component had qualitatively big and reasonable effect. Now as day of year effect is sensitive to prior choice, but it’s not clear how much better Cauchy prior distribution is we use LOO-CV to compare the models.
loo8 <- fit8$loo()
loo8tnu <- fit8tnu$loo()
loo_compare(list(`Model 8 normal`=loo8,`Model 8 Student\'s t`=loo8tnu))
elpd_diff se_diff
Model 8 Student's t 0.0 0.0
<<<<<<< HEAD
Model 8 normal -122.7 15.9
=======
Model 8 normal -118.8 15.6
>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
As we could have expected based on the posterior of nu_f4 Student’s t prior on day of year effects is better. As low degrees of freedom indicate a thick tailed distribution for day of year effect is needed, we decided to test again RHS prior.
Model 8+RHS: day of year effect with RHS prior
Model 5 had RHS prior but the problem was that optimization result wasn’t even close to sensible and MCMC was very slow. Given the other models we now know that the problem is not in adding day of year effect or combining it with time dependent magnitude for the day of week effect. It was easier now to focus on figuring out the problem in RHS. Since RHS is presented as a scale mixture of normals involving hierarchical prior, it is common to use non-centered parameterization for RHS prior. Non-centered parameterization is useful when the information from the likelihood is weak and the prior dependency dominates in the posterior dependency. RHS is often used when there are less observations than unknowns. In this problem each unknown (one day of year effect) is informed by several observations from different years, and then it might be that the centered parameterization is better. And this turned out to be true and the inference for model 8 with centered parameterization RHS prior on day of year effect worked much better than for model 5. (In Stan it was easy to test switch from non-centered to centered parameterization by removing the multplier from one of the parameter declarations).
Compile Stan model 8 + RHS gpbf8rhs.stan
model8rhs <- cmdstan_model(stan_file = root("Birthdays", "gpbf8rhs.stan"),
include_paths = root("Birthdays"))
Add a global scale for RHS prior
standata8 <- c(standata8,
scale_global=0.1) # global scale for RHS prior
Optimizing is faster than sampling (although this result can be useful in a quick workflow, the result should not be used as the final result).
opt8rhs <- model8rhs$optimize(data=standata8, init=0.1, algorithm='lbfgs',
history=100, tol_obj=10)
odraws8rhs <- opt8rhs$draws()
Sample short chains using the optimization result as initial values (although the result from short chains can be useful in a quick workflow, the result should not be used as the final result).
init8rhs <- sapply(c('intercept0','lengthscale_f1','lengthscale_f2','lengthscale_g3',
'sigma_f1','sigma_f2','sigma_g3','sigma_f4','sigma',
'beta_f1','beta_f2','beta_f3','beta_g3','beta_f4','beta_f5',
'tau_f4','lambda_f4','caux_f4'),
function(variable) {as.numeric(subset(odraws8rhs, variable=variable))})
fit8rhs <- model8rhs$sample(data=standata8, iter_warmup=100, iter_sampling=100, chains=4, parallel_chains=4,
init=function() { init8rhs }, refresh=10)
Check whether parameters have reasonable values
draws8rhs <- fit8rhs$draws()
summarise_draws(subset(draws8rhs, variable=c('intercept','sigma_','lengthscale_','sigma','nu_'), regex=TRUE))
<<<<<<< HEAD
# A tibble: 9 x 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 intercept0 0.69 0.65 0.32 0.22 0.28 1.4 2.0 5.8 15.
2 sigma_f1 1.6 1.6 0.37 0.36 1.2 2.2 2.0 5.8 28.
3 sigma_f2 0.28 0.27 0.046 0.040 0.24 0.37 1.7 6.7 12.
4 sigma_g3 0.18 0.18 0.056 0.065 0.12 0.29 2.2 5.6 16.
5 sigma_f4 0.15 0.15 0.0060 0.0048 0.14 0.16 1.2 244. 180.
6 lengthscale_f1 0.38 0.40 0.090 0.088 0.20 0.47 1.9 6.1 27.
7 lengthscale_f2 0.24 0.24 0.015 0.016 0.22 0.26 1.5 8.0 61.
8 lengthscale_g3 0.77 0.74 0.20 0.26 0.55 1.1 1.9 6.1 25.
9 sigma 0.25 0.25 0.0021 0.0025 0.24 0.25 1.2 13. 185.
=======
# A tibble: 9 × 10
variable mean median sd mad q5 q95 rhat ess_bulk ess_tail
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 intercept0 0.34 0.34 0.0068 0.0083 0.33 0.35 1.3 12. NA
2 sigma_f1 1.5 1.4 0.28 0.016 1.3 2.2 2.2 6.3 NA
3 sigma_f2 0.28 0.28 0.030 0.046 0.23 0.31 2.1 5.7 NA
4 sigma_g3 0.23 0.19 0.078 0.027 0.15 0.36 1.8 6.4 NA
5 sigma_f4 0.16 0.16 0.0075 0.0065 0.14 0.16 1.9 6.1 NA
6 lengthscale_f1 0.27 0.30 0.068 0.098 0.17 0.39 1.5 9.3 NA
7 lengthscale_f2 0.23 0.23 0.013 0.011 0.21 0.25 1.4 11. NA
8 lengthscale_g3 0.65 0.59 0.20 0.20 0.41 0.92 1.6 7.4 NA
9 sigma 0.25 0.25 0.0016 0.0014 0.24 0.25 1.2 39. NA
>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
Compare the model to the data
draws8 <- as_draws_matrix(draws8rhs)
Ef <- exp(apply(subset(draws8, variable='f'), 2, median))
Ef1 <- apply(subset(draws8, variable='f1'), 2, median)
Ef1 <- exp(Ef1 - mean(Ef1) + mean(log(data$births_relative100)))
Ef2 <- apply(subset(draws8, variable='f2'), 2, median)
Ef2 <- exp(Ef2 - mean(Ef2) + mean(log(data$births_relative100)))
Ef_day_of_week <- apply(subset(draws8, variable='f_day_of_week'), 2, median)
Ef_day_of_week <- exp(Ef_day_of_week - mean(Ef_day_of_week) + mean(log(data$births_relative100)))
Ef3 <- apply(subset(draws8, variable='f3'), 2, median)
Ef3 <- exp(Ef3 - mean(Ef3) + mean(log(data$births_relative100)))
Ef4 <- apply(subset(draws8, variable='beta_f4'), 2, median)*sd(log(data$births_relative100))
Ef4 <- exp(Ef4)*100
Efloats <- apply(subset(draws8, variable='beta_f5'), 2, median)*sd(log(data$births_relative100))
Efloats <- exp(Efloats)*100
floats1988<-c(memorial_days[20], labor_days[c(20,40)], thanksgiving_days[c(20,40)])-6939
Ef4float <- Ef4
Ef4float[floats1988] <- Ef4float[floats1988]*Efloats[c(1,2,2,3,3)]/100
pf <- data %>%
mutate(Ef = Ef) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_point(aes(y=Ef), color=set1[1], alpha=0.2) +
labs(x="Date", y="Relative number of births")
pf1 <- data %>%
mutate(Ef1 = Ef1) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_line(aes(y=Ef1), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births")
pf2 <- data %>%
mutate(Ef2 = Ef2) %>%
group_by(day_of_year2) %>%
summarise(meanbirths=mean(births_relative100), meanEf2=mean(Ef2)) %>%
ggplot(aes(x=as.Date("1987-12-31")+day_of_year2, y=meanbirths)) + geom_point(color=set1[2], alpha=0.2) +
scale_x_date(date_breaks = "1 month", date_labels = "%b") +
geom_line(aes(y=meanEf2), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of year")
pf3 <- ggplot(data=data, aes(x=day_of_week, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
scale_x_continuous(breaks = 1:7, labels=c('Mon','Tue','Wed','Thu','Fri','Sat','Sun')) +
geom_line(data=data.frame(x=1:7,y=Ef_day_of_week), aes(x=x, y=Ef_day_of_week), color=set1[1]) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of week")
N=length(data$id)
pf3b <- data %>%
mutate(Ef3 = Ef3*Ef1/100) %>%
ggplot(aes(x=date, y=births_relative100)) + geom_point(color=set1[2], alpha=0.2) +
geom_point(aes(y=Ef3), color=set1[1], size=0.1) +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births") +
annotate("text",x=as.Date("1989-08-01"),y=(Ef3*Ef1/100)[c((N-5):(N-4), N, N-6)],label=c("Mon","Tue","Sat","Sun"))
f13 <- data %>% filter(year==1988)%>%select(day,date)%>%mutate(y=Ef4float)%>%filter(day==13)
pf2b <-data.frame(x=as.Date("1988-01-01")+0:365, y=Ef4float) %>%
ggplot(aes(x=x,y=y)) + geom_line(color=set1[1]) +
scale_x_date(date_breaks = "1 month", date_labels = "%b") +
geom_hline(yintercept=100, color='gray') +
labs(x="Date", y="Relative number of births of year") +
annotate("text",x=as.Date("1988-01-01"),y=Ef4float[1]-1,label="New year") +
annotate("text",x=as.Date("1988-02-14"),y=Ef4float[45]+1.5,label="Valentine's day") +
annotate("text",x=as.Date("1988-02-29"),y=Ef4float[60]-2.5,label="Leap day") +
annotate("text",x=as.Date("1988-04-01"),y=Ef4float[92]-1.5,label="April 1st") +
annotate("text",x=as.Date("1988-07-04"),y=Ef4float[186]-1.5,label="Independence day") +
annotate("text",x=as.Date("1988-10-31"),y=Ef4float[305]-1.5,label="Halloween") +
annotate("text",x=as.Date("1988-12-24"),y=Ef4float[360]-2,label="Christmas") +
annotate("text",x=as.Date("1988-05-30"),y=Ef4float[151]-2,label="Memorial day") +
annotate("text",x=as.Date("1988-09-05"),y=Ef4float[249]-1.5,label="Labor day") +
annotate("text",x=as.Date("1988-11-24"),y=Ef4float[329]-1,label="Thanksgiving")+
geom_point(data=f13,aes(x=date,y=y), size=3, shape=1)
(pf + pf1) / (pf2 + pf3b) / (pf2b)
<<<<<<< HEAD

=======

>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
Visually we get quite similar result as with Cauchy prior. When we compare the models with LOO-CV, Cauchy is favored instead of RHS.
loo8rhs<-fit8rhs$loo()
loo_compare(list(`Model 8 Students t`=loo8tnu,`Model 8 RHS`=loo8rhs))
elpd_diff se_diff
Model 8 Students t 0.0 0.0
<<<<<<< HEAD
Model 8 RHS -46.8 17.6
=======
Model 8 RHS -27.0 18.9
>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
If we look at the LOO-stacking model weights, the predictive performance can be improved by combining Cauchy and RHS priors on day of year effect which indicates that neither of them is very close to true distribution.
loo_model_weights(list(`Model 8 Students t`=loo8tnu,`Model 8 RHS`=loo8rhs))
Method: stacking
------
weight
<<<<<<< HEAD
Model 8 Students t 0.721
Model 8 RHS 0.279
=======
Model 8 Students t 0.636
Model 8 RHS 0.364
>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
Further improvements for the day of year effect
It’s unlikely that day of year effect would be unstructured with some distribution like Cauchy, and thus instead of trying to find a prior distribution that would improve LOO-CV, it would make more sense to further add structural information. For example, it would be possible to add more known special days and take into account that a special day effect and weekend effect probably are not additive. Furthermore if there are less births during some day, the births need to happen some other day and it can be assumed that there would be corresponding excess of births before of after a bank holiday. This ringing around days with less births is not simple as it is also affected whether the previous and following days are weekend days. This all gets more complicated than we want to include in this case study, but the reader can see how the similar gradual model building could be made by adding additional components. Eventually it is likely that there starts to be worry of overfitting, but integration over the unknown alleviates that and looking at the predictive performance estimates such LOO-CV can help to decide when the additional model components don’t improve the predictive performance or can’t be well identified.
Residual analysis
We can get further ideas for how to improve the model also by looking at the residuals.
draws8 <- as_draws_matrix(draws8tnu)
Ef <- exp(apply(subset(draws8, variable='f'), 2, median))
data %>%
mutate(Ef = Ef) %>%
ggplot(aes(x=date, y=log(births_relative100/Ef))) + geom_point(color=set1[2]) +
geom_hline(yintercept=0, color='gray') +
scale_x_date(date_breaks = "1 year", date_labels = "%Y") +
theme(panel.grid.major.x=element_line(color='gray',size=1))
<<<<<<< HEAD

=======

>>>>>>> 435a1869c466d9e0b7c0ff67b2d2dce66c4f8656
We can see some structure, specifically in years 1969–1978 the residual has negative peak in the middle of the year, while in years 1981–1988 the residual has positive peak in the middle of the year. This kind of pattern appears as we use the same seasonal effect for all years, but the magnitude of seasonal effect is changing. It would be possible to modify the model to include gradually changing seasonal effect, but leave it out from this case study.
The best model so far explains already 94% of the variance (LOO-R2).
draws8 <- as_draws_matrix(draws8tnu)
f <- exp(subset(draws8, variable='f'))
loo8tnu <- fit8tnu$loo(save_psis=TRUE)
Efloo <- E_loo(f, psis_object=loo8tnu$psis_object)$value
LOOR2 <- 1-var(log(data$births_relative100/Efloo))/var(log(data$births_relative100))
print(LOOR2, digits=2)
[1] 0.94
As it seems we could still improve by adding more structure and time varying seasonal effect, it seems the variability in the number of births from day to day is quite well predictable. Of course big part of the variation is due to planned induced births and c-sections, and thus hospitals do already control the number of births per day and there is no really practical use for the result. However there are plenty of similar time series, for example, in consumer behavior that are affected by special days.
More accurate inference
During all the iterative model building we favored optimization and short MCMC chains. In the end we also run with higher adapt_delta to reduce the probability of divergences, higher maximum treedepth to ensure higher effective sample size per iteration (ESS per second doesn’t necessarily improve), and run much longer chains, but didn’t see practical differences in plots or LOO-CV values. As running these longer chains can take hours they are not run as part of this notebook. An example of how to reduce probability of divergences and increase maximum treedepth is shown below (there is rarely need to increase adapt_delta larger than 0.95 and if there are still divergences with adapt_delta equal to 0.99, the posterior has serious problems and it should be considered whether re-parameterization, better data or more informative priors could help).
## fit8tnu <- model8tnu$sample(data=standata8, chains=4, parallel_chains=4,
## adapt_delta=0.95, max_treedepth=15)
IycgLS0tCiMnIHRpdGxlOiAiQmF5ZXNpYW4gd29ya2Zsb3cgYm9vayAtIEJpcnRoZGF5cyIKIycgYXV0aG9yOiAiR2VsbWFuLCBWZWh0YXJpLCBTaW1wc29uLCBldCBhbCIKIycgZGF0ZTogIkZpcnN0IHZlcnNpb24gMjAyMC0xMi0yOC4gTGFzdCBtb2RpZmllZCBgciBmb3JtYXQoU3lzLkRhdGUoKSlgLiIKIycgb3V0cHV0OgojJyAgIGh0bWxfZG9jdW1lbnQ6CiMnICAgICB0aGVtZTogcmVhZGFibGUKIycgICAgIHRvYzogdHJ1ZQojJyAgICAgdG9jX2RlcHRoOiAzCiMnICAgICB0b2NfZmxvYXQ6IHRydWUKIycgICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKIycgLS0tCgojJyBXb3JrZmxvdyBmb3IgaXRlcmF0aXZlIGJ1aWxkaW5nIG9mIGEgdGltZSBzZXJpZXMgbW9kZWwuCiMnCiMnIFdlIGFuYWx5c2UgdGhlIHJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgcGVyIGRheSBpbiBVU0EgMTk2OS0xOTg4CiMnIHVzaW5nIEdhdXNzaWFuIHByb2Nlc3MgdGltZSBzZXJpZXMgbW9kZWwgd2l0aCBzZXZlcmFsIG1vZGVsCiMnIGNvbXBvbmVudHMgdGhhdCBjYW4gZXhwbGFpbiB0aGUgbG9uZyB0ZXJtLCBzZWFzb25hbCwgd2Vla2x5LCBkYXkgb2YKIycgeWVhciwgYW5kIHNwZWNpYWwgZmxvYXRpbmQgZGF5IHZhcmlhdGlvbi4KIycKIycgU3RhbiBtb2RlbCBjb2RlcyBhcmUgYXZhaWxhYmxlIGluIFt0aGUgY29ycmVzcG9uZGluZyBnaXQgcmVwb10oaHR0cHM6Ly9naXRodWIuY29tL2F2ZWh0YXJpL2Nhc2VzdHVkaWVzL3RyZWUvbWFzdGVyL0JpcnRoZGF5cykKIycKIycgLS0tLS0tLS0tLS0tLQojJyAKCiMrIHNldHVwLCBpbmNsdWRlPUZBTFNFCmtuaXRyOjpvcHRzX2NodW5rJHNldChtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRSwgd2FybmluZz1GQUxTRSwgY29tbWVudD1OQSwgY2FjaGU9RkFMU0UpCiMgc3dpdGNoIHRoaXMgdG8gVFJVRSB0byBzYXZlIGZpZ3VyZXMgaW4gc2VwYXJhdGUgZmlsZXMKc2F2ZWZpZ3MgPC0gRkFMU0UKCiMnICMjIyMgTG9hZCBwYWNrYWdlcwpsaWJyYXJ5KCJycHJvanJvb3QiKQpyb290PC1oYXNfZmlsZSgiLldvcmtmbG93LUV4YW1wbGVzLXJvb3QiKSRtYWtlX2ZpeF9maWxlKCkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoY21kc3RhbnIpCmxpYnJhcnkocG9zdGVyaW9yKQpvcHRpb25zKHBpbGxhci5uZWcgPSBGQUxTRSwgcGlsbGFyLnN1YnRsZT1GQUxTRSwgcGlsbGFyLnNpZ2ZpZz0yKQpsaWJyYXJ5KGxvbykKbGlicmFyeShiYXllc3Bsb3QpCnRoZW1lX3NldChiYXllc3Bsb3Q6OnRoZW1lX2RlZmF1bHQoYmFzZV9mYW1pbHkgPSAic2FucyIpKQpsaWJyYXJ5KHBhdGNod29yaykKc2V0MSA8LSBSQ29sb3JCcmV3ZXI6OmJyZXdlci5wYWwoNywgIlNldDEiKQoKIycgIyMgTG9hZCBhbmQgcGxvdCBkYXRhCiMnIAojJyBMb2FkIGJpcnRoZGF5cyBwZXIgZGF5IGluIFVTQSAxOTY5LTE5ODg6CmRhdGEgPC0gcmVhZF9jc3Yocm9vdCgiQmlydGhkYXlzL2RhdGEiLCAiYmlydGhzX3VzYV8xOTY5LmNzdiIpKQoKIycgQWRkIGRhdGUgdHlwZSBjb2x1bW4gZm9yIHBsb3R0aW5nCmRhdGEgPC0gZGF0YSAlPiUKICBtdXRhdGUoZGF0ZSA9IGFzLkRhdGUoIjE5NjgtMTItMzEiKSArIGlkLAogICAgICAgICBiaXJ0aHNfcmVsYXRpdmUxMDAgPSBiaXJ0aHMvbWVhbihiaXJ0aHMpKjEwMCkKCiMnICMjIyBQbG90IGFsbCBiaXJ0aHMKIycKIycgV2UgY2FuIHNlZSBzbG93IHZhcmlhdGlvbiBpbiB0cmVuZCwgeWVhcmx5IHBhdHRlcm4sIGFuZCBlc3BlY2lhbGx5CiMnIGluIHRoZSBsYXRlciB5ZWFycyBzcHJlYWQgdG8gbG93ZXIgYW5kIGhpZ2hlciB2YWx1ZXMuCmRhdGEgJT4lCiAgZ2dwbG90KGFlcyh4PWRhdGUsIHk9YmlydGhzKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0pICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIikKCiMnICMjIyBQbG90IGFsbCBiaXJ0aHMgYXMgcmVsYXRpdmUgdG8gbWVhbgojJwojJyBUbyBtYWtlIHRoZSBpbnRlcnByZXRhdGlvbiB3ZSBzd2l0Y2ggdG8gZXhhbWluZSB0aGUgcmVsYXRpdmUKIycgY2hhbmdlLCB3aXRoIHRoZSBtZWFuIGxldmVsIGRlbm90ZWQgd2l0aCAxMDAuCmRhdGEgJT4lCiAgZ2dwbG90KGFlcyh4PWRhdGUsIHk9YmlydGhzX3JlbGF0aXZlMTAwKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBiaXJ0aHMgcGVyIGRheSIpCgojJyAjIyMgUGxvdCBtZWFuIHBlciBkYXkgb2YgeWVhcgojJwojJyBXZSBjYW4gc2VlIHRoZSBnZW5lcmljIHBhdHRlcm4gaW4geWVhcmx5IHNlYXNvbmFsIHRyZW5kIHNpbXBseSBieQojJyBhdmVyYWdpbmcgb3ZlciBlYWNoIGRheSBvZiB5ZWFyIChkYXlfb2ZfeWVhciBoYXMgbnVtYmVycyBmcm9tIDEgdG8KIycgMzY2IGV2ZXJ5IHllYXIgd2l0aCBsZWFwIGRheSBiZWluZyA2MCBhbmQgMXN0IE1hcmNoIDYxIGFsc28gb24KIycgbm9uLWxlYXAteWVhcnMpLgpkYXRhICU+JQogIGdyb3VwX2J5KGRheV9vZl95ZWFyMikgJT4lCiAgc3VtbWFyaXNlKG1lYW5iaXJ0aHM9bWVhbihiaXJ0aHNfcmVsYXRpdmUxMDApKSAlPiUKICBnZ3Bsb3QoYWVzKHg9YXMuRGF0ZSgiMTk4Ni0xMi0zMSIpK2RheV9vZl95ZWFyMiwgeT1tZWFuYmlydGhzKSkgKwogIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKSArCiAgbGFicyh4PSJEYXkgb2YgeWVhciIsIHk9IlJlbGF0aXZlIGJpcnRocyBwZXIgZGF5IG9mIHllYXIiKQoKIycgIyMjIFBsb3QgbWVhbiBwZXIgZGF5IG9mIHdlZWsKIycgCiMnIFdlIGNhbiBzZWUgdGhlIGdlbmVyaWMgcGF0dGVybiBpbiB3ZWVrbHkgdHJlbmQgc2ltcGx5IGJ5IGF2ZXJhZ2luZwojJyBvdmVyIGVhY2ggZGF5IG9mIHdlZWsuCmRhdGEgJT4lCiAgZ3JvdXBfYnkoZGF5X29mX3dlZWspICU+JQogIHN1bW1hcmlzZShtZWFuYmlydGhzPW1lYW4oYmlydGhzX3JlbGF0aXZlMTAwKSkgJT4lCiAgZ2dwbG90KGFlcyh4PWRheV9vZl93ZWVrLCB5PW1lYW5iaXJ0aHMpKSArCiAgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBzaXplPTQpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gMTo3LCBsYWJlbHM9YygnTW9uJywnVHVlJywnV2VkJywnVGh1JywnRnJpJywnU2F0JywnU3VuJykpICsKICBsYWJzKHg9IkRheSBvZiB3ZWVrIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyBvZiB3ZWVrIikKCiMnICMjIFByZXZpb3VzIGFuYWx5c2VzCiMnIAojJyBXZSBoYXZlIGFuYWx5c2VkIHRoZSBzYW1lIGRhdGEgYmVmb3JlIGluIEJEQTMgYW5kIHRodXMgaGFkIGlkZWEgb2YKIycgd2hhdCBraW5kIG9mIG1vZGVsIHRvIHVzZS4gRm9yIEJEQTMgd2UgdXNlZCBHUHN0dWZmIHNvZnR3YXJlIHdoaWNoCiMnIGlzIEdhdXNzaWFuIHByb2Nlc3Mgc3BlY2lmaWMgc29mdHdhcmUgZm9yIE1hdGxhYiBhbmQgT2N0YXZlLiBBcwojJyBTdGFuIGhhcyBhaW1lZCB0byBiZSB2ZXJ5IGdlbmVyaWMgaXQgY2FuIGJlIHNsb3dlciB0aGFuIHNwZWNpYWxpemVkCiMnIHNvZnR3YXJlIGZvciBzb21lIHNwZWNpZmljIG1vZGVscyBzdWNoIGFzIEdhdXNzaWFuIHByb2Nlc3NlcywgYnV0CiMnIFN0YW4gcHJvdmlkZXMgbW9yZSBmbGV4aWJpbGl0eSBpbiB0aGUgbW9kZWwgZGVmaW5pdGlvbi4KIycKIycgUml1dG9ydC1NYXlvbCBldCBhbCAoMjAyMCkgZGVtb25zdHJhdGUgSGlsYmVydCBzcGFjZSBhcHByb3hpbWF0ZQojJyBiYXNpcyBmdW5jdGlvbiBhcHByb3hpbWF0aW9uIG9mIEdhdXNzaWFuIHByb2Nlc3NlcyBhbHNvIGZvciB0aGUKIycgc2FtZSBiaXJ0aGRheSBkYXRhLiBJbiB0aGUgZXhwZXJpbWVudHMgdGhlIGluZmVyZW5jZSB3YXMgc2xvd2VyCiMnIHRoYW4gZXhwZWN0ZWQgcmFpc2luZyBzdXNwaWNpb24gb2YgaW5lZmZpY2llbnQgbW9kZWwgY29kZSBvciBiYWQKIycgcG9zdGVyaW9yIHNoYXBlIGR1ZSB0byBiYWQgbW9kZWwgc3BlY2lmaWNhdGlvbi4KIycKIycgIyMgV29ya2Zsb3cgZm9yIHF1aWNrIGl0ZXJhdGl2ZSBtb2RlbCBidWlsZGluZwojJwojJyBFdmVuIHdlIGhhdmUgZ2VuZXJhbCBpZGVhIGZvciB0aGUgbW9kZWwgKHNsb3cgdHJlbmQsIHNlYXNvbmFsCiMnIHRyZW5kLCB3ZWVrZGF5IGVmZmVjdCwgZXRjKSwgYWRkaW5nIHRoZW0gYWxsIGF0IG9uY2UgdG8gdGhlIG1vZGVsCiMnIG1ha2VzIHRoZSBtb2RlbCBjb21wbGV4IGFuZCBkaWZmaWN1bHQgdG8gZGVidWcgYW5kIHNvbHZlIHRoZQojJyBjb21wdXRhdGlvbmFsIHByb2JsZW1zLiBJdCBpcyB0aHVzIG5hdHVyYWwgdG8gYnVpbGQgdGhlIG1vZGVsCiMnIGdyYWR1YWxseSBhbmQgY2hlY2sgdGhhdCBlYWNoIGFkZGl0aW9uIHdvcmtzIGJlZm9yZSBhZGRpbmcgdGhlIG5leHQKIycgbW9kZWwgY29tcG9uZW50LiBEdXJpbmcgdGhpcyBpdGVyYXRpdmUgbW9kZWwgYnVpbGRpbmcgd2Ugd2FudCB0aGUKIycgaW5mZXJlbmNlIHRvIGJlIGZhc3QsIGJ1dCBpdCBkb2Vzbid0IG5lZWQgdG8gYmUgdmVyeSBhY2N1cmF0ZSBhcwojJyBsb25nIGFzIHF1YWxpdGF0aXZlbHkgdGhlIG5ldyBtb2RlbCBpcyByZWFzb25hYmxlLiBGb3IgcXVpY2sKIycgdGVzdGluZyBhbmQgaXRlcmF0aXZlIG1vZGVsIGJ1aWxkaW5nIHdlIGNhbiB1c2Ugb3B0aW1pemF0aW9uIGFuZAojJyBzaG9ydGVyIE1DTUMgY2hhaW5zIHRoYXQgd2Ugd291bGQgbm90IHJlY29tbWVuZCBmb3IgdGhlIGZpbmFsCiMnIGluZmVyZW5jZS4gIEZ1cnRoZXJtb3JlLCBpbiB0aGlzIHNwZWNpZmljIGV4YW1wbGUsIHRoZSBuZXcKIycgYWRkaXRpb25zIGFyZSBxdWFsaXRhdGl2ZWx5IHNvIGNsZWFyIGltcHJvdmVtZW50cyB0aGF0IHRoZXJlIGlzIG5vCiMnIG5lZWQgZm9yIHF1YW50aXRhdGl2ZSBtb2RlbCBjb21wYXJpc29uIHdoZXRoZXIgdGhlIGFkZGl0aW9ucyBhcmUKIycgYGBzaWduaWZpY2FudCcnIChzZWUgYWxzbyBOYXZhcnJvLCAyMDE5KSBhbmQgdGhlcmUgaXMgbm8gZGFuZ2VyIG9mCiMnIG92ZXJmaXR0aW5nLiBBbHRob3VnaCB0aGVyZSBpcyBvbmUgcGFydCBvZiB0aGUgbW9kZWwgd2hlcmUgdGhlIGRhdGEKIycgaXMgd2Vha2x5IGluZm9ybWF0aXZlIGFuZCB0aGUgcHJpb3IgY2hvaWNlcyBzZWVtIHRvIG1hdHRlciBhbmQKIycgd2UnbGwgZ2V0IGJhY2sgdG8gdGhpcyBhbmQgY29uc2VxdWVuY2VzIGxhdGVyLiBPdmVyYWxsIHdlIGJ1aWxkCiMnIHRlbnMgb2YgZGlmZmVyZW50IG1vZGVscyBidXQgaWxsdXN0cmF0ZSBoZXJlIG9ubHkgdGhlIG1haW4gbGluZS4KIycgCgojJyAjIyBNb2RlbHMgZm9yIHJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aGRheXMKIycKIycgQXMgdGhlIHJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgaXMgcG9zaXRpdmUgaXQncyBuYXR1cmFsIHRvIG1vZGVsCiMnIHRoZSBsb2dhcml0aG0gdmFsdWUuIFRoZSBnZW5lcmljIGZvcm0gb2YgdGhlIG1vZGVscyBpcwojJyAkJAojJyB5IFxzaW0gXG1ib3h7bm9ybWFsfShmKHgpLCBcc2lnbWEpLAojJyAkJAojJyB3aGVyZSAkZiQgaXMgZGlmZmVyZW50IGFuZCBncmFkdWFsbHkgbW9yZSBjb21wbGV4IGZ1bmN0aW9uCiMnIGNvbmRpdGlvbmFsIG9uICR4JCB0aGF0IGluY2x1ZGVzIHJ1bm5pbmcgZGF5IG51bWJlciwgZGF5IG9mIHllYXIsCiMnIGRheSBvZiB3ZWVrIGFuZCBldmVudHVhbGx5IHNvbWUgc3BlY2lhbCBmbG9hdGluZyBVUyBiYW5rIGhvbGlkYXlzLgojJwojJyAjIyMgTW9kZWwgMTogU2xvdyB0cmVuZAojJwojJyBUaGUgbW9kZWwgMSBpcyBqdXN0IHRoZSBzbG93IHRyZW5kIG92ZXIgdGhlIHllYXJzIHVzaW5nIEhpbGJlcnQKIycgc3BhY2UgYmFzaXMgZnVuY3Rpb24gYXBwcm94aW1hdGVkIEdhdXNzaWFuIHByb2Nlc3MKIycgJCQKIycgZiA9IFxtYm94e2ludGVyY2VwdH0gKyBmXzFcXAojJyBcbWJveHtpbnRlcmNlcHR9IFxzaW0gXG1ib3h7bm9ybWFsfSgwLDEpXFwKIycgZl8xIFxzaW0gXG1ib3h7R1B9KDAsS18xKQojJyAkJAojJyB3aGVyZSBHUCBoYXMgZXhwb25lbnRpYXRlZCBxdWFkcmF0aWMgY292YXJpYW5jZSBmdW5jdGlvbi4KIycgCiMnIEluIHRoaXMgcGhhc2UgdGhlIGNvZGUgZnJvbSBSaXV0b3J0LU1heW9sIGV0IGFsLigyMDIwKSB3YXMgY2xlYW5lZAojJyBhbmQgd3JpdHRlbiB0byBiZSBtb3JlIGVmZmljaWVudCwgYnV0IG9ubHkgdGhlIG9uZSBHUCBjb21wb25lbnQgd2FzCiMnIGluY2x1ZGVkIHRvIG1ha2UgdGhlIHRlc3RpbmcgZWFzaWVyLiBBbHRob3VnaCB0aGUgY29kZSB3YXMgbWFkZQojJyBtb3JlIGVmZmljaWVudCwgdGhlIGFpbSB3YXNuJ3QgdG8gbWFrZSBpdCB0aGUgZmFzdGVzdCBwb3NzaWJsZSBhcwojJyB0aGUgbGF0ZXIgbW9kZWwgY2hhbmdlcyBtYXkgaGF2ZSBiaWdnZXIgZWZmZWN0IG9uIHRoZSBwZXJmb3JtYW5jZQojJyAoaXQncyBnb29kIG8gYXZvaWQgcHJlbWF0dXJlIG9wdGltaXphdGlvbikuIFdlIGFsc28gdXNlIHF1aXRlIHNtYWxsCiMnIG51bWJlciBvZiBiYXNpcyBmdW5jdGlvbnMgdG8gbWFrZSB0aGUgY29kZSBydW4gZmFzdGVyLCBhbmQgb25seQojJyBsYXRlciBleGFtaW5lIG1vcmUgY2FyZWZ1bGx5IHdoZXRoZXIgdGhlIG51bWJlciBvZiBiYXNpcyBmdW5jdGlvbgojJyBpcyBzdWZmaWNpZW50IGNvbXBhcmVkIHRvIHRoZSBwb3N0ZXJpb3Igb2YgdGhlIGxlbmd0aCBzY2FsZSAoc2VlLAojJyBSaXV0b3J0LU1heW9sIGV0IGFsLiwgMjAyMCkuCiMnCgojJyBDb21waWxlIFN0YW4gbW9kZWwgW2dwYmYxLnN0YW5dKGh0dHBzOi8vZ2l0aHViLmNvbS9hdmVodGFyaS9jYXNlc3R1ZGllcy9ibG9iL21hc3Rlci9CaXJ0aGRheXMvZ3BiZjEuc3Rhbikgd2hpY2ggaW5jbHVkZXMgW2dwYmFzaXNmdW5fZnVuY3Rpb25zLnN0YW5dKGh0dHBzOi8vZ2l0aHViLmNvbS9hdmVodGFyaS9jYXNlc3R1ZGllcy9ibG9iL21hc3Rlci9CaXJ0aGRheXMvZ3BiYXNpc2Z1bl9mdW5jdGlvbnMuc3RhbikKIysgbW9kZWwxLCByZXN1bHRzPSdoaWRlJwptb2RlbDEgPC0gY21kc3Rhbl9tb2RlbChzdGFuX2ZpbGUgPSByb290KCJCaXJ0aGRheXMiLCAiZ3BiZjEuc3RhbiIpLAogICAgICAgICAgICAgICAgICAgICAgICBpbmNsdWRlX3BhdGhzID0gcm9vdCgiQmlydGhkYXlzIikpCiMnIERhdGEgdG8gYmUgcGFzc2VkIHRvIFN0YW4Kc3RhbmRhdGExIDwtIGxpc3QoeD1kYXRhJGlkLAogICAgICAgICAgICAgICAgICB5PWxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCksCiAgICAgICAgICAgICAgICAgIE49bGVuZ3RoKGRhdGEkaWQpLAogICAgICAgICAgICAgICAgICBjX2YxPTEuNSwgIyBmYWN0b3IgYyBvZiBiYXNpcyBmdW5jdGlvbnMgZm9yIEdQIGZvciBmMQogICAgICAgICAgICAgICAgICBNX2YxPTEwKSAgIyBudW1iZXIgb2YgYmFzaXMgZnVuY3Rpb25zIGZvciBHUCBmb3IgZjEKCiMnIEFzIHRoZSBiYXNpcyBmdW5jdGlvbiBhcHByb3hpbWF0aW9uIGFuZCBwcmlvcnMgcmVzdHJpY3QgdGhlCiMnIGNvbXBsZXhpdHkgb2YgR1AsIHdlIGNhbiBzYWZlbHkgdXNlIG9wdGltaXphdGlvbiB0byBnZXQgYSB2ZXJ5CiMnIHF1aWNrIGluaXRpYWwgcmVzdWx0IHRvIGNoZWNrIHRoYXQgdGhlIG1vZGVsIGNvZGUgaXMgY29tcHV0aW5nIHdoYXQKIycgd2UgaW50ZW5kZWQuIEFzIHRoZXJlIGFyZSBvbmx5IDE0IHBhcmFtZXRlcnMgYW5kIDczMDUgb2JzZXJ2YXRpb25zCiMnIGl0J3MgbGlrZWx5IHRoYXQgdGhlIHBvc3RlcmlvciBpcyBjbG9zZSB0byBub3JtYWwgKGluIHVuY29uc3RyYWluZWQKIycgc3BhY2UpLiBJbiB0aGlzIGNhc2UgdGhlIG9wdGltaXphdGlvbiB0YWtlcyBsZXNzIHRoYW4gb25lIHNlY29uZAojJyB3aGlsZSBNQ01DIHNhbXBsaW5nIHdpdGggZGVmYXVsdCBvcHRpb25zIHdvdWxkIGhhdmUgdGFrZW4gc2V2ZXJhbAojJyBtaW51dGVzLiBBbHRob3VnaCB0aGlzIHJlc3VsdCBjYW4gYmUgdXNlZnVsIGluIGEgcXVpY2sgd29ya2Zsb3csCiMnIHRoZSByZXN1bHQgc2hvdWxkIG5vdCBiZSB1c2VkIGFzIHRoZSBmaW5hbCByZXN1bHQuCiMrIG9wdDEsIHJlc3VsdHM9J2hpZGUnCm9wdDEgPC0gbW9kZWwxJG9wdGltaXplKGRhdGEgPSBzdGFuZGF0YTEsIGluaXQ9MCwgYWxnb3JpdGhtPSdiZmdzJykKIycgQ2hlY2sgd2hldGhlciBwYXJhbWV0ZXJzIGhhdmUgcmVhc29uYWJsZSB2YWx1ZXMKb2RyYXdzMSA8LSBvcHQxJGRyYXdzKCkKc3Vic2V0KG9kcmF3czEsIHZhcmlhYmxlPWMoJ2ludGVyY2VwdCcsJ3NpZ21hX2YxJywnbGVuZ3Roc2NhbGVfZjEnLCdzaWdtYScpKQoKIycgQ29tcGFyZSB0aGUgbW9kZWwgdG8gdGhlIGRhdGEKb0VmIDwtIGV4cChhcy5udW1lcmljKHN1YnNldChvZHJhd3MxLCB2YXJpYWJsZT0nZicpKSkKZGF0YSAlPiUKICBtdXRhdGUob0VmID0gb0VmKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArCiAgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBnZW9tX2xpbmUoYWVzKHk9b0VmKSwgY29sb3I9c2V0MVsxXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMiKQoKIycgQWZ0ZXIgd2UgZ2V0IHRoZSBtb2RlbCB3b3JraW5nIHVzaW5nIG9wdGltaXphdGlvbiB3ZSBjYW4gY29tcGFyZQojJyB0aGUgcmVzdWx0IHRvIHVzaW5nIHNob3J0IE1DTUMgY2hhaW5zIHdoaWNoIHdpbGwgYWxzbyBwcm92aWRlIHVzCiMnIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gb24gc3BlZWQgb2YgZGlmZmVyZW50IGNvZGUgaW1wbGVtZW50YXRpb25zCiMnIGZvciB0aGUgc2FtZSBtb2RlbC4gV2UgaW50ZW50aW9uYWxseSB1c2UganVzdCAxLzEwdGggbGVuZ3RoIGZyb20KIycgdGhlIHVzdWFsIHJlY29tbWVuZGF0aW9uLCBhcyBkdXJpbmcgdGhlIGl0ZXJhdGl2ZSBtb2RlbCBidWlsZGluZyBhCiMnIHJvdWdoIHJlc3VsdHMgYXJlIHN1ZmZpY2llbnQuIFdoZW4gdGVzdGluZyB0aGUgY29kZSB3ZSBpbml0aWFsbHkKIycgdXNlZCBqdXN0IG9uZSBjaGFpbiwgYnV0IGF0IHRoaXMgcG9pbnQgcnVubmluZyBmb3VyIGNoYWlucyB3aXRoCiMnIGZvdXIgY29yZSBDUFUgZG9lc24ndCBhZGQgbXVjaCB0byB0aGUgd2FsbCBjbG9jayB0aW1lLCBidXQgZ2l2ZXMKIycgbW9yZSBpbmZvcm1hdGlvbiBvZiBob3cgZWFzeSBpdCBpcyBzYW1wbGUgZnJvbSB0aGUgcG9zdGVyaW9yIGFuZAojJyBjYW4gcmV2ZWFsIGlmIHRoZXJlIGFyZSBtdWx0aXBsZSBtb2Rlcy4gQWx0aG91Z2ggdGhlIHJlc3VsdCBmcm9tCiMnIHNob3J0IGNoYWlucyBjYW4gYmUgdXNlZnVsIGluIGEgcXVpY2sgd29ya2Zsb3csIHRoZSByZXN1bHQgc2hvdWxkCiMnIG5vdCBiZSB1c2VkIGFzIHRoIGZpbmFsIHJlc3VsdC4KIysgZml0MSwgcmVzdWx0cz0naGlkZScKZml0MSA8LSBtb2RlbDEkc2FtcGxlKGRhdGE9c3RhbmRhdGExLCBpdGVyX3dhcm11cD0xMDAsIGl0ZXJfc2FtcGxpbmc9MTAwLAogICAgICAgICAgICAgICAgICAgICAgY2hhaW5zPTQsIHBhcmFsbGVsX2NoYWlucz00LCBzZWVkPTM4OTEpCgojJyBEZXBlbmRpbmcgb24gdGhlIHJhbmRvbSBzZWVkIGFuZCBsdWNrLCB3ZSBzb21ldGltZXMgb2JzZXJ2ZWQgdGhhdAojJyBzb21lIG9mIHRoZSBjaGFpbnMgZ290IHN0dWNrIGluIGRpZmZlcmVudCBtb2Rlcy4gV2UgY291bGQgc2VlIHRoaXMKIycgaW4gaGlnaCBSaGF0IGFuZCBsb3cgRVNTIGRpYWdub3N0aWMgdmFsdWVzLgpkcmF3czEgPC0gZml0MSRkcmF3cygpCnN1bW1hcmlzZV9kcmF3cyhzdWJzZXQoZHJhd3MxLCB2YXJpYWJsZT1jKCdpbnRlcmNlcHQnLCdzaWdtYV9mMScsJ2xlbmd0aHNjYWxlX2YxJywnc2lnbWEnKSkpCiMnIEV4YW1pbmluZyB0aGUgdHJhY2UgcGxvdHMgc2hvd3MgdGhlIG11bHRpbW9kYWxpdHkgY2xlYXJseS4KbWNtY190cmFjZShkcmF3czEsIHJlZ2V4X3BhcnM9YygnaW50ZXJjZXB0Jywnc2lnbWFfZjEnLCdsZW5ndGhzY2FsZV9mMScsJ3NpZ21hJykpCgojJyBJbiB0aGlzIGNhc2UgaXQgd2FzIGVhc3kgdG8gZmlndXJlIG91dCB0aGF0IHNvbWUgb2YgdGhlIGNoYWlucyBnb3QKIycgc3R1Y2sgaW4gcXVhbGl0YXRpdmVseSBtdWNoIHdvcnNlIG1vZGVzLiBXZSBkb24ndCBpbiBnZW5lcmFsCiMnIHJlY29tbWVuZCB0byBzdGFydCBmcm9tIHRoZSBtb2RlIGFzIHRoZSBtb2RlIGlzIG5vdCB1c3VhbGx5CiMnIHJlcHJlc2VudGF0aXZlIHBvaW50IGluIGhpZXJhcmNoaWNhbCBtb2RlbCBwb3N0ZXJpb3Igb3IgaW4gaGlnaAojJyBkaW1lbnNpb25hbCBwb3N0ZXJpb3IsIGJ1dCB3ZSBjYW4gdXNlIHRoaXMgYWdhaW4gdG8gc3BlZWQgdXAgdGhlCiMnIGl0ZXJhdGl2ZSBtb2RlbCBidWlsZGluZyBhcyBsb25nIGFzIHdlIGNoZWNrIHRoYXQgdGhlIG9wdGltaXphdGlvbgojJyByZXN1bHQgaXMgc2Vuc2libGUgYW5kIGxhdGVyIGRvIG1vcmUgY2FyZWZ1bCBpbmZlcmVuY2UuIEFsdGhvdWdoCiMnIHRoZSByZXN1bHQgZnJvbSBzaG9ydCBjaGFpbnMgY2FuIGJlIHVzZWZ1bCBpbiBhIHF1aWNrIHdvcmtmbG93LCB0aGUKIycgcmVzdWx0IHNob3VsZCBub3QgYmUgdXNlZCBhcyB0aGUgZmluYWwgcmVzdWx0Lgppbml0MSA8LSBzYXBwbHkoYygnaW50ZXJjZXB0Jywnc2lnbWFfZjEnLCdsZW5ndGhzY2FsZV9mMScsJ2JldGFfZjEnLCdzaWdtYScpLAogICAgICAgICAgICAgICAgZnVuY3Rpb24odmFyaWFibGUpIHthcy5udW1lcmljKHN1YnNldChvZHJhd3MxLCB2YXJpYWJsZT12YXJpYWJsZSkpfSkKIysgZml0MWluaXQsIHJlc3VsdHM9J2hpZGUnCmZpdDEgPC0gbW9kZWwxJHNhbXBsZShkYXRhPXN0YW5kYXRhMSwgaXRlcl93YXJtdXA9MTAwLCBpdGVyX3NhbXBsaW5nPTEwMCwKICAgICAgICAgICAgICAgICAgICAgIGNoYWlucz00LCBwYXJhbGxlbF9jaGFpbnM9NCwKICAgICAgICAgICAgICAgICAgICAgIGluaXQ9ZnVuY3Rpb24oKSB7IGluaXQxIH0pCgojJyBXZSBub3cgb2JzZXJ2ZSBiZXR0ZXIgUmhhdCBhbmQgRVNTIGRpYWdub3N0aWMgdmFsdWVzLCBhbHRob3VnaCBkdWUKIycgdG8gdmVyeSBzaG9ydCBjaGFpbnMgdGhleSBhcmUgbm90IHlldCBwZXJmZWN0LiBXZSBhcmUgbGlrZWx5IHRvCiMnIGFsc28gb2JzZXJ2ZSBIYW1pbHRvbmlhbiBNb250ZSBDYXJsbyBkaXZlcmdlbmNlcyBhbmQgdHJlZWRlcHRoCiMnIGV4Y2VlZGVuY2VzIGluIGR5bmFtaWMgYnVpbGRpbmcgb2YgdGhlIEhhbWlsdG9uaWFuIHRyYWplY3RvcnksCiMnIGJ1dCB0aGVyZSBpcyBubyBuZWVkIHRvIHdvcnJ5IGFib3V0IHRob3NlIGFzIGxvbmcgYXMgdGhlCiMnIG1vZGVsIHJlc3VsdHMgYXJlIHF1YWxpdGF0aXZlbHkgc2Vuc2libGUgYXMgdGhlc2UgY29tcHV0YXRpb25hbAojJyBpc3N1ZXMgY2FuIGFsc28gZ28gYXdheSB3aGVuIHRoZSBtb2RlbCBpdHNlbGYgaXMgaW1wcm92ZWQuIEluIGFsbAojJyB0aGUgZm9sbG93aW5nIHNob3J0IE1DTUMgc2FtcGxpbmdzIHdlIGdldCBzb21lIG9yIG1hbnkgZGl2ZXJnZW5jZXMKIycgYW5kIHVzdWFsbHkgdmVyeSBsYXJnZSBudW1iZXIgb2YgdHJlZWRlcHRoIGV4Y2VlZGVuY2VzLiBEaXZlcmdlbmNlcwojJyBpbmRpY2F0ZSBwb3NzaWJsZSBiaWFzIGFuZCBzaG91bGQgYmUgZXZlbnR1YWxseSBpbnZlc3RpZ2F0ZWQKIycgY2FyZWZ1bGx5LiBUcmVlZGVwdGggZXhjZWVkZW5jZXMgaW5kaWNhdGUgc3Ryb25nIHBvc3RlcmlvcgojJyBkZXBlbmRlbmNpZXMgYW5kIHNsb3cgbWl4aW5nIGFuZCBzb21ldGltZXMgdGhlIHBvc3RlcmlvciBjYW4gYmUKIycgbXVjaCBpbXByb3ZlZCBieSBjaGFuZ2luZyB0aGUgcGFyYW1ldGVyaXphdGlvbiBvciBwcmlvcnMsIGJ1dCBhcwojJyB0aGUgdHJlZWRlcHRoIGV4Y2VlZGVuY2VzIGRvbid0IGluZGljYXRlIGJpYXMgdGhlcmUgaXMgbm8gbmVlZCBmb3IKIycgbW9yZSBjYXJlZnVsIGFuYWx5c2lzIGlmIHRoZSByZXN1bHRpbmcgRVNTIGFuZCBNQ1NFIHZhbHVlcyBhcmUgZ29vZAojJyBmb3IgdGhlIHB1cnBvc2UgaW4gaGFuZC4gIFdlJ2xsIGNvbWUgYmFjayBsYXRlciB0byBtb3JlIGNhcmVmdWwKIycgYW5hbHlzaXMgb2YgdGhlIGZpbmFsIG1vZGVscy4KZHJhd3MxIDwtIGZpdDEkZHJhd3MoKQpzdW1tYXJpc2VfZHJhd3Moc3Vic2V0KGRyYXdzMSwgdmFyaWFibGU9YygnaW50ZXJjZXB0Jywnc2lnbWFfZjEnLCdsZW5ndGhzY2FsZV9mMScsJ3NpZ21hJykpKQojJyBUcmFjZSBwbG90IHNob3dzIHNsb3cgbWl4aW5nIGJ1dCBubyBtdWx0aW1vZGFsaXR5LgptY21jX3RyYWNlKGRyYXdzMSwgcmVnZXhfcGFycz1jKCdpbnRlcmNlcHQnLCdzaWdtYV9mMScsJ2xlbmd0aHNjYWxlX2YxJywnc2lnbWEnKSkKCiMnIFRoZSBtb2RlbCByZXN1bHQgZnJvbSBzaG9ydCBNQ01DIGNoYWlucyBsb29rcyB2ZXJ5IHNpbWlsYXIgdG8gdGhlCiMnIG9wdGltaXphdGlvbiByZXN1bHQuCmRyYXdzMSA8LSBhc19kcmF3c19tYXRyaXgoZHJhd3MxKQpFZiA8LSBleHAoYXBwbHkoc3Vic2V0KGRyYXdzMSwgdmFyaWFibGU9J2YnKSwgMiwgbWVkaWFuKSkKZGF0YSAlPiUKICBtdXRhdGUoRWYgPSBFZikgJT4lCiAgZ2dwbG90KGFlcyh4PWRhdGUsIHk9YmlydGhzX3JlbGF0aXZlMTAwKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIGdlb21fbGluZShhZXMoeT1FZiksIGNvbG9yPXNldDFbMV0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIikKCiMnIElmIHdlIGNvbXBhcmUgdGhlIHJlc3VsdCBmcm9tIHNob3J0IHNhbXBsaW5nIHRvIG9wdGltaXppbmcsIHdlCiMnIGRvbid0IHNlZSBwcmFjdGljYWwgZGlmZmVyZW5jZSBpbiB0aGUgcHJlZGljdGlvbnMgKGFsdGhvdWdoIHdlIHNlZQojJyBsYXRlciBtb3JlIGRpZmZlcmVuY2VzIGJldHdlZW4gb3B0aW1pemF0aW9uIGFuZCBNQ01DKS4KZGF0YSAlPiUKICBtdXRhdGUoRWYgPSBFZiwKICAgICAgICAgb0VmID0gb0VmKSAlPiUKICBnZ3Bsb3QoYWVzKHg9RWYsIHk9b0VmKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0pICsKICBnZW9tX2FibGluZSgpICsKICBsYWJzKHg9IkVmIGZyb20gc2hvcnQgTWFya292IGNoYWluIiwgeT0iRWYgZnJvbSBvcHRpbWl6aW5nIikKCiMnICMjIyBNb2RlbCAyOiBTbG93IHRyZW5kICsgeWVhcmx5IHNlYXNvbmFsIHRyZW5kCiMnIAojJyBUaGUgbW9kZWwgMiBhZGRzIHllYXJseSBzZWFzb25hbCB0cmVuZCB1c2luZyBHUCB3aXRoIHBlcmlvZGljCiMnIGNvdmFyaWFuY2UgZnVuY3Rpb24uCiMnICQkCiMnIGYgPSBcbWJveHtpbnRlcmNlcHR9ICsgZl8xICsgZl8yIFxcCiMnIFxtYm94e2ludGVyY2VwdH0gXHNpbSBcbWJveHtub3JtYWx9KDAsMSlcXAojJyBmXzEgXHNpbSBcbWJveHtHUH0oMCxLXzEpXFwKIycgZl8yIFxzaW0gXG1ib3h7R1B9KDAsS18yKQojJyAkJAojJyB3aGVyZSB0aGUgZmlyc3QgR1AgdXNlcyB0aGUgZXhwb25lbnRpYXRlZCBxdWFkcmF0aWMgY292YXJpYW5jZQojJyBmdW5jdGlvbiwgYW5kIHRoZSBzZWNvbmQgb25lIGEgcGVyaW9kaWMgY292YXJpYW5jZSBmdW5jdGlvbi4gTW9zdAojJyB5ZWFycyBoYXZlIDM2NSBjYWxlbmRhciBkYXlzIGFuZCBldmVyeSBmb3VyIHllYXJzIChkdXJpbmcgdGhlIGRhdGEKIycgcmFuZ2UpIHRoZXJlIGFyZSAzNjYgZGF5cywgYW5kIHRodXMgd2Ugc2ltcGxpZnkgYW5kIHVzZSBwZXJpb2Qgb2YKIycgMzY1LjI1IGZvciB0aGUgcGVyaW9kaWMgY29tcG9uZW50LAojJwojJyBUaGUgZmlyc3QgdmVyc2lvbiBvZiBtb2RlbCAyIHdpdGggdGhlIGFkZGVkIHBlcmlvZGljIGNvbXBvbmVudAojJyBmb2xsb3dpbmcgZnJvbSBSaXV0b3J0LU1heW9sICgyMDIwKSB0dXJuZWQgb3V0IGJlIHZlcnkgc2xvdy4gV2l0aAojJyB0aGUgZGVmYXVsdCBNQ01DIG9wdGlvbnMgdGhlIGluZmVyZW5jZSB3b3VsZCBoYXZlIHRha2VuIGhvdXJzLCBidXQKIycgd2l0aCB0aGUgc2hvcnQgY2hhaW5zIGl0IHdhcyBwb3NzaWJsZSB0byBpbmZlciB0aGF0IHNvbWV0aGluZyBoYXMKIycgdG8gYmUgd3JvbmcuIFRoZSBtb2RlbCBvdXRwdXQgd2FzIHNlbnNpYmxlLCBidXQgZGlhZ25vc3RpY3MKIycgaW5kaWNhdGVkIHZlcnkgc2xvdyBtaXhpbmcuIEJ5IG1vcmUgY2FyZWZ1bCBleGFtaW5hdGlvbiBvZiB0aGUKIycgbW9kZWwgaXQgdHVybmVkIG91dCB0aGF0IHRoZSBwZXJpb2RpYyBjb21wb25lbnQgd2FzIGluY2x1ZGluZwojJyBhbm90aGVyIGludGVyY2VwdCB0ZXJtIGFuZCB3aXRoIHR3byBpbnRlcmNlcHQgdGVybXMgdGhlaXIgc3VtIHdhcwojJyB3ZWxsIGluZm9ybWVkIGJ5IHRoZSBkYXRhLCBidXQgaW5kaXZpZHVhbGx5IHRoZXkgd2VyZSBub3Qgd2VsbAojJyBpbmZvcm1lZCBhbmQgdGh1cyB0aGUgcG9zdGVyaW9ycyB3ZXJlIHdpZGUsIHdoaWNoIGxlYWQgdG8gdmVyeSBzbG93CiMnIG1peGluZy4gVGhpcyBiYWQgbW9kZWwgaXMgbm90IHNob3duIGhlcmUsIGJ1dCB0aGUgb3B0aW1pemF0aW9uLAojJyBzaG9ydCBNQ01DIGNoYWlucyBhbmQgc2FtcGxpbmcgZGlhZ25vc3RpYyB0b29scyB3ZXJlIGNydWNpYWwgZm9yCiMnIGZhc3QgZXhwZXJpbWVudGF0aW9uIGFuZCBzb2x2aW5nIHRoZSBwcm9ibGVtLgojJyAKIycgQ29tcGlsZSBTdGFuIG1vZGVsIDIgKHRoZSBmaXhlZCB2ZXJzaW9uKSBbZ3BiZjIuc3Rhbl0oaHR0cHM6Ly9naXRodWIuY29tL2F2ZWh0YXJpL2Nhc2VzdHVkaWVzL2Jsb2IvbWFzdGVyL0JpcnRoZGF5cy9ncGJmMi5zdGFuKQojKyBtb2RlbDIsIHJlc3VsdHM9J2hpZGUnCm1vZGVsMiA8LSBjbWRzdGFuX21vZGVsKHN0YW5fZmlsZSA9IHJvb3QoIkJpcnRoZGF5cyIsICJncGJmMi5zdGFuIiksCiAgICAgICAgICAgICAgICAgICAgICAgIGluY2x1ZGVfcGF0aHMgPSByb290KCJCaXJ0aGRheXMiKSkKCiMnIERhdGEgdG8gYmUgcGFzc2VkIHRvIFN0YW4Kc3RhbmRhdGEyIDwtIGxpc3QoeD1kYXRhJGlkLAogICAgICAgICAgICAgICAgICB5PWxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCksCiAgICAgICAgICAgICAgICAgIE49bGVuZ3RoKGRhdGEkaWQpLAogICAgICAgICAgICAgICAgICBjX2YxPTEuNSwgIyBmYWN0b3IgYyBvZiBiYXNpcyBmdW5jdGlvbnMgZm9yIEdQIGZvciBmMQogICAgICAgICAgICAgICAgICBNX2YxPTEwLCAgIyBudW1iZXIgb2YgYmFzaXMgZnVuY3Rpb25zIGZvciBHUCBmb3IgZjEKICAgICAgICAgICAgICAgICAgSl9mMj0yMCkgICMgbnVtYmVyIG9mIGJhc2lzIGZ1bmN0aW9ucyBmb3IgcGVyaW9kaWMgZjIKCiMnIE9wdGltaXppbmcgaXMgZmFzdGVyIHRoYW4gc2FtcGxpbmcgKGFsdGhvdWdoIHRoaXMgcmVzdWx0IGNhbiBiZQojJyB1c2VmdWwgaW4gYSBxdWljayB3b3JrZmxvdywgdGhlIHJlc3VsdCBzaG91bGQgbm90IGJlIHVzZWQgYXMgdGhlCiMnIGZpbmFsIHJlc3VsdCkuCiMrIG9wdDIsIHJlc3VsdHM9J2hpZGUnCm9wdDIgPC0gbW9kZWwyJG9wdGltaXplKGRhdGE9c3RhbmRhdGEyLCBpbml0PTAsIGFsZ29yaXRobT0nYmZncycpCgojJyBDaGVjayB3aGV0aGVyIHBhcmFtZXRlcnMgaGF2ZSByZWFzb25hYmxlIHZhbHVlcwpvZHJhd3MyIDwtIG9wdDIkZHJhd3MoKQpzdWJzZXQob2RyYXdzMiwgdmFyaWFibGU9YygnaW50ZXJjZXB0Jywnc2lnbWFfJywnbGVuZ3Roc2NhbGVfJywnc2lnbWEnKSwgcmVnZXg9VFJVRSkKCiMnIENvbXBhcmUgdGhlIG1vZGVsIHRvIHRoZSBkYXRhCkVmIDwtIGV4cChhcy5udW1lcmljKHN1YnNldChvZHJhd3MyLCB2YXJpYWJsZT0nZicpKSkKRWYxIDwtIGFzLm51bWVyaWMoc3Vic2V0KG9kcmF3czIsIHZhcmlhYmxlPSdmMScpKQpFZjEgPC0gZXhwKEVmMSAtIG1lYW4oRWYxKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCkVmMiA8LSBhcy5udW1lcmljKHN1YnNldChvZHJhd3MyLCB2YXJpYWJsZT0nZjInKSkKRWYyIDwtIGV4cChFZjIgLSBtZWFuKEVmMikgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpwZiA8LSBkYXRhICU+JQogIG11dGF0ZShFZiA9IEVmKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9saW5lKGFlcyh5PUVmKSwgY29sb3I9c2V0MVsxXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMiKQpwZjEgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYxID0gRWYxKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9saW5lKGFlcyh5PUVmMSksIGNvbG9yPXNldDFbMV0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIikKcGYyIDwtIGRhdGEgJT4lCiAgbXV0YXRlKEVmMiA9IEVmMikgJT4lCiAgZ3JvdXBfYnkoZGF5X29mX3llYXIyKSAlPiUKICBzdW1tYXJpc2UobWVhbmJpcnRocz1tZWFuKGJpcnRoc19yZWxhdGl2ZTEwMCksIG1lYW5FZjI9bWVhbihFZjIpKSAlPiUKICBnZ3Bsb3QoYWVzKHg9YXMuRGF0ZSgiMTk4Ny0xMi0zMSIpK2RheV9vZl95ZWFyMiwgeT1tZWFuYmlydGhzKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKSArCiAgZ2VvbV9saW5lKGFlcyh5PW1lYW5FZjIpLCBjb2xvcj1zZXQxWzFdKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyBvZiB5ZWFyIikKcGYgLyAocGYxICsgcGYyKQoKIycgU2FtcGxlIHNob3J0IGNoYWlucyB1c2luZyB0aGUgb3B0aW1pemF0aW9uIHJlc3VsdCBhcyBpbml0aWFsIHZhbHVlcwojJyAoYWx0aG91Z2ggdGhlIHJlc3VsdCBmcm9tIHNob3J0IGNoYWlucyBjYW4gYmUgdXNlZnVsIGluIGEgcXVpY2sKIycgd29ya2Zsb3csIHRoZSByZXN1bHQgc2hvdWxkIG5vdCBiZSB1c2VkIGFzIHRoZSBmaW5hbCByZXN1bHQpLgppbml0MiA8LSBzYXBwbHkoYygnaW50ZXJjZXB0JywnbGVuZ3Roc2NhbGVfZjEnLCdsZW5ndGhzY2FsZV9mMicsJ3NpZ21hX2YxJywnc2lnbWFfZjInLCdzaWdtYScsJ2JldGFfZjEnLCdiZXRhX2YyJyksCiAgICAgICAgICAgICAgICBmdW5jdGlvbih2YXJpYWJsZSkge2FzLm51bWVyaWMoc3Vic2V0KG9kcmF3czIsIHZhcmlhYmxlPXZhcmlhYmxlKSl9KQojKyBmaXQyLCByZXN1bHRzPSdoaWRlJwpmaXQyIDwtIG1vZGVsMiRzYW1wbGUoZGF0YT1zdGFuZGF0YTIsIGl0ZXJfd2FybXVwPTEwMCwgaXRlcl9zYW1wbGluZz0xMDAsCiAgICAgICAgICAgICAgICAgICAgICBjaGFpbnM9NCwgcGFyYWxsZWxfY2hhaW5zPTQsCiAgICAgICAgICAgICAgICAgICAgICBpbml0PWZ1bmN0aW9uKCkgeyBpbml0MiB9KQoKIycgQ2hlY2sgd2hldGhlciBwYXJhbWV0ZXJzIGhhdmUgcmVhc29uYWJsZSB2YWx1ZXMKZHJhd3MyIDwtIGZpdDIkZHJhd3MoKQpzdW1tYXJpc2VfZHJhd3Moc3Vic2V0KGRyYXdzMiwgdmFyaWFibGU9YygnaW50ZXJjZXB0Jywnc2lnbWFfJywnbGVuZ3Roc2NhbGVfJywnc2lnbWEnKSwgcmVnZXg9VFJVRSkpCgojJyBDb21wYXJlIHRoZSBtb2RlbCB0byB0aGUgZGF0YQpkcmF3czIgPC0gYXNfZHJhd3NfbWF0cml4KGRyYXdzMikKRWYgPC0gZXhwKGFwcGx5KHN1YnNldChkcmF3czIsIHZhcmlhYmxlPSdmJyksIDIsIG1lZGlhbikpCkVmMSA8LSBhcHBseShzdWJzZXQoZHJhd3MyLCB2YXJpYWJsZT0nZjEnKSwgMiwgbWVkaWFuKQpFZjEgPC0gZXhwKEVmMSAtIG1lYW4oRWYxKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCkVmMiA8LSBhcHBseShzdWJzZXQoZHJhd3MyLCB2YXJpYWJsZT0nZjInKSwgMiwgbWVkaWFuKQpFZjIgPC0gZXhwKEVmMiAtIG1lYW4oRWYyKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCnBmIDwtIGRhdGEgJT4lCiAgbXV0YXRlKEVmID0gRWYpICU+JQogIGdncGxvdChhZXMoeD1kYXRlLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBnZW9tX2xpbmUoYWVzKHk9RWYpLCBjb2xvcj1zZXQxWzFdKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyIpCnBmMSA8LSBkYXRhICU+JQogIG11dGF0ZShFZjEgPSBFZjEpICU+JQogIGdncGxvdChhZXMoeD1kYXRlLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBnZW9tX2xpbmUoYWVzKHk9RWYxKSwgY29sb3I9c2V0MVsxXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMiKQpwZjIgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYyID0gRWYyKSAlPiUKICBncm91cF9ieShkYXlfb2ZfeWVhcjIpICU+JQogIHN1bW1hcmlzZShtZWFuYmlydGhzPW1lYW4oYmlydGhzX3JlbGF0aXZlMTAwKSwgbWVhbkVmMj1tZWFuKEVmMikpICU+JQogIGdncGxvdChhZXMoeD1hcy5EYXRlKCIxOTg3LTEyLTMxIikrZGF5X29mX3llYXIyLCB5PW1lYW5iaXJ0aHMpKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCBkYXRlX2xhYmVscyA9ICIlYiIpICsKICBnZW9tX2xpbmUoYWVzKHk9bWVhbkVmMiksIGNvbG9yPXNldDFbMV0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIG9mIHllYXIiKQpwZiAvIChwZjEgKyBwZjIpCgojJyBTZWFzb25hbCBjb21wb25lbnQgaGFzIHJlYXNvbmFibGUgZml0IHRvIHRoZSBkYXRhLgojJyAKCiMnICMjIyBNb2RlbCAzOiBTbG93IHRyZW5kICsgeWVhcmx5IHNlYXNvbmFsIHRyZW5kICsgZGF5IG9mIHdlZWsKIycKIycgQmFzZWQgb24gdGhlIHF1aWNrIHBsb3R0aW5nIG9mIHRoZSBkYXRhIGFib3ZlLCBkYXkgb2Ygd2VlayBoYXMgYQojJyBjbGVhciBlZmZlY3QgYW5kIHRoZXJlIGFyZSBsZXNzIGJhYmllcyBib3JuIG9uIFNhdHVyZGF5IGFuZAojJyBTdW5kYXkuIFRoaXMgY2FuIGJlIHRha2VuIGludG8gYWNjb3VudCB3aXRoIHNpbXBsZSBhZGRpdGl2ZQojJyBjb2VmZmljaWVudHMuIFdlIGZpeCB0aGUgZWZmZWN0IG9mIE1vbmRheSB0byAwIGFuZCBoYXZlIGFkZGl0aW9uYWwKIycgY29lZmZpY2llbnRzIGZvciBvdGhlciB3ZWVrZGF5cy4KIycgJCQKIycgZiA9IFxtYm94e2ludGVyY2VwdH0gKyBmXzEgKyBmXzIgKyBcYmV0YV97XG1ib3h7ZGF5IG9mIHdlZWt9fSBcXAojJyBcbWJveHtpbnRlcmNlcHR9IFxzaW0gXG1ib3h7bm9ybWFsfSgwLDEpXFwKIycgZl8xIFxzaW0gXG1ib3h7R1B9KDAsS18xKVxcCiMnIGZfMiBcc2ltIFxtYm94e0dQfSgwLEtfMilcXAojJyBcYmV0YV97XG1ib3h7ZGF5IG9mIHdlZWt9fSA9IDAgXHF1YWQgXG1ib3h7aWYgZGF5IG9mIHdlZWsgaXMgTW9uZGF5fVxcCiMnIFxiZXRhX3tcbWJveHtkYXkgb2Ygd2Vla319IFxzaW0gXG1ib3h7bm9ybWFsfSgwLDEpIFxxdWFkIFxtYm94e2lmIGRheSBvZiB3ZWVrIGlzIG5vdCBNb25kYXl9CiMnICQkCiMnIAojJyBDb21waWxlIFN0YW4gbW9kZWwgMyBbZ3BiZjMuc3Rhbl0oaHR0cHM6Ly9naXRodWIuY29tL2F2ZWh0YXJpL2Nhc2VzdHVkaWVzL2Jsb2IvbWFzdGVyL0JpcnRoZGF5cy9ncGJmMy5zdGFuKQojKyBtb2RlbDMsIHJlc3VsdHM9J2hpZGUnCm1vZGVsMyA8LSBjbWRzdGFuX21vZGVsKHN0YW5fZmlsZSA9IHJvb3QoIkJpcnRoZGF5cyIsICJncGJmMy5zdGFuIiksCiAgICAgICAgICAgICAgICAgICAgICAgIGluY2x1ZGVfcGF0aHMgPSByb290KCJCaXJ0aGRheXMiKSkKCiMnIERhdGEgdG8gYmUgcGFzc2VkIHRvIFN0YW4Kc3RhbmRhdGEzIDwtIGxpc3QoeD1kYXRhJGlkLAogICAgICAgICAgICAgICAgICB5PWxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCksCiAgICAgICAgICAgICAgICAgIE49bGVuZ3RoKGRhdGEkaWQpLAogICAgICAgICAgICAgICAgICBjX2YxPTEuNSwgIyBmYWN0b3IgYyBvZiBiYXNpcyBmdW5jdGlvbnMgZm9yIEdQIGZvciBmMQogICAgICAgICAgICAgICAgICBNX2YxPTEwLCAgIyBudW1iZXIgb2YgYmFzaXMgZnVuY3Rpb25zIGZvciBHUCBmb3IgZjEKICAgICAgICAgICAgICAgICAgSl9mMj0yMCwgICMgbnVtYmVyIG9mIGJhc2lzIGZ1bmN0aW9ucyBmb3IgcGVyaW9kaWMgZjIKICAgICAgICAgICAgICAgICAgZGF5X29mX3dlZWs9ZGF0YSRkYXlfb2Zfd2VlaykKCiMnIE9wdGltaXppbmcgaXMgZmFzdGVyIHRoYW4gc2FtcGxpbmcgKGFsdGhvdWdoIHRoaXMgcmVzdWx0IGNhbiBiZQojJyB1c2VmdWwgaW4gYSBxdWljayB3b3JrZmxvdywgdGhlIHJlc3VsdCBzaG91bGQgbm90IGJlIHVzZWQgYXMgdGhlCiMnIGZpbmFsIHJlc3VsdCkuCiMrIG9wdDMsIHJlc3VsdHM9J2hpZGUnCm9wdDMgPC0gbW9kZWwzJG9wdGltaXplKGRhdGE9c3RhbmRhdGEzLCBpbml0PTAsIGFsZ29yaXRobT0nYmZncycpCgojJyBDaGVjayB3aGV0aGVyIHBhcmFtZXRlcnMgaGF2ZSByZWFzb25hYmxlIHZhbHVlcwpvZHJhd3MzIDwtIG9wdDMkZHJhd3MoKQpzdWJzZXQob2RyYXdzMywgdmFyaWFibGU9YygnaW50ZXJjZXB0Jywnc2lnbWFfJywnbGVuZ3Roc2NhbGVfJywnc2lnbWEnKSwgcmVnZXg9VFJVRSkKc3Vic2V0KG9kcmF3czMsIHZhcmlhYmxlPWMoJ2JldGFfZjMnKSkKCiMnIENvbXBhcmUgdGhlIG1vZGVsIHRvIHRoZSBkYXRhCkVmIDwtIGV4cChhcy5udW1lcmljKHN1YnNldChvZHJhd3MzLCB2YXJpYWJsZT0nZicpKSkKRWYxIDwtIGFzLm51bWVyaWMoc3Vic2V0KG9kcmF3czMsIHZhcmlhYmxlPSdmMScpKQpFZjEgPC0gZXhwKEVmMSAtIG1lYW4oRWYxKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCkVmMiA8LSBhcy5udW1lcmljKHN1YnNldChvZHJhd3MzLCB2YXJpYWJsZT0nZjInKSkKRWYyIDwtIGV4cChFZjIgLSBtZWFuKEVmMikgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZl9kYXlfb2Zfd2VlayA8LSBhcy5udW1lcmljKHN1YnNldChvZHJhd3MzLCB2YXJpYWJsZT0nZl9kYXlfb2Zfd2VlaycpKQpFZl9kYXlfb2Zfd2VlayA8LSBleHAoRWZfZGF5X29mX3dlZWsgLSBtZWFuKEVmX2RheV9vZl93ZWVrKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCnBmIDwtIGRhdGEgJT4lCiAgbXV0YXRlKEVmID0gRWYpICU+JQogIGdncGxvdChhZXMoeD1kYXRlLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBnZW9tX2xpbmUoYWVzKHk9RWYpLCBjb2xvcj1zZXQxWzFdLCBhbHBoYT0wLjc1KSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyIpCnBmMSA8LSBkYXRhICU+JQogIG11dGF0ZShFZjEgPSBFZjEpICU+JQogIGdncGxvdChhZXMoeD1kYXRlLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBnZW9tX2xpbmUoYWVzKHk9RWYxKSwgY29sb3I9c2V0MVsxXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMiKQpwZjIgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYyID0gRWYyKSAlPiUKICBncm91cF9ieShkYXlfb2ZfeWVhcjIpICU+JQogIHN1bW1hcmlzZShtZWFuYmlydGhzPW1lYW4oYmlydGhzX3JlbGF0aXZlMTAwKSwgbWVhbkVmMj1tZWFuKEVmMikpICU+JQogIGdncGxvdChhZXMoeD1hcy5EYXRlKCIxOTg3LTEyLTMxIikrZGF5X29mX3llYXIyLCB5PW1lYW5iaXJ0aHMpKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCBkYXRlX2xhYmVscyA9ICIlYiIpICsKICBnZW9tX2xpbmUoYWVzKHk9bWVhbkVmMiksIGNvbG9yPXNldDFbMV0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIG9mIHllYXIiKQpwZjMgPC0gZ2dwbG90KGRhdGE9ZGF0YSwgYWVzKHg9ZGF5X29mX3dlZWssIHk9YmlydGhzX3JlbGF0aXZlMTAwKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSAxOjcsIGxhYmVscz1jKCdNb24nLCdUdWUnLCdXZWQnLCdUaHUnLCdGcmknLCdTYXQnLCdTdW4nKSkgKwogIGdlb21fbGluZShkYXRhPWRhdGEuZnJhbWUoeD0xOjcseT1FZl9kYXlfb2Zfd2VlayksIGFlcyh4PXgsIHk9RWZfZGF5X29mX3dlZWspLCBjb2xvcj1zZXQxWzFdKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyBvZiB3ZWVrIikKKHBmICsgcGYxKSAvIChwZjIgKyBwZjMpCgojJyBTYW1wbGUgc2hvcnQgY2hhaW5zIHVzaW5nIHRoZSBvcHRpbWl6YXRpb24gcmVzdWx0IGFzIGluaXRpYWwgdmFsdWVzCiMnIChhbHRob3VnaCB0aGUgcmVzdWx0IGZyb20gc2hvcnQgY2hhaW5zIGNhbiBiZSB1c2VmdWwgaW4gYSBxdWljawojJyB3b3JrZmxvdywgdGhlIHJlc3VsdCBzaG91bGQgbm90IGJlIHVzZWQgYXMgdGhlIGZpbmFsIHJlc3VsdCkuCmluaXQzIDwtIHNhcHBseShjKCdpbnRlcmNlcHQwJywnbGVuZ3Roc2NhbGVfZjEnLCdsZW5ndGhzY2FsZV9mMicsJ3NpZ21hX2YxJywnc2lnbWFfZjInLCdzaWdtYScsCiAgICAgICAgICAgICAgICAgICdiZXRhX2YxJywnYmV0YV9mMicsJ2JldGFfZjMnKSwKICAgICAgICAgICAgICAgIGZ1bmN0aW9uKHZhcmlhYmxlKSB7YXMubnVtZXJpYyhzdWJzZXQob2RyYXdzMywgdmFyaWFibGU9dmFyaWFibGUpKX0pCiMrIGZpdDMsIHJlc3VsdHM9J2hpZGUnCmZpdDMgPC0gbW9kZWwzJHNhbXBsZShkYXRhPXN0YW5kYXRhMywgaXRlcl93YXJtdXA9MTAwLCBpdGVyX3NhbXBsaW5nPTEwMCwKICAgICAgICAgICAgICAgICAgICAgIGNoYWlucz00LCBwYXJhbGxlbF9jaGFpbnM9NCwKICAgICAgICAgICAgICAgICAgICAgIGluaXQ9ZnVuY3Rpb24oKSB7IGluaXQzIH0pCgojJyBDaGVjayB3aGV0aGVyIHBhcmFtZXRlcnMgaGF2ZSByZWFzb25hYmxlIHZhbHVlcwpkcmF3czMgPC0gZml0MyRkcmF3cygpCnN1bW1hcmlzZV9kcmF3cyhzdWJzZXQoZHJhd3MzLCB2YXJpYWJsZT1jKCdpbnRlcmNlcHQnLCdzaWdtYV8nLCdsZW5ndGhzY2FsZV8nLCdzaWdtYScpLCByZWdleD1UUlVFKSkKc3VtbWFyaXNlX2RyYXdzKHN1YnNldChkcmF3czMsIHZhcmlhYmxlPWMoJ2JldGFfZjMnKSkpCgojJyBDb21wYXJlIHRoZSBtb2RlbCB0byB0aGUgZGF0YQpkcmF3czMgPC0gYXNfZHJhd3NfbWF0cml4KGRyYXdzMykKRWYgPC0gZXhwKGFwcGx5KHN1YnNldChkcmF3czMsIHZhcmlhYmxlPSdmJyksIDIsIG1lZGlhbikpCkVmMSA8LSBhcHBseShzdWJzZXQoZHJhd3MzLCB2YXJpYWJsZT0nZjEnKSwgMiwgbWVkaWFuKQpFZjEgPC0gZXhwKEVmMSAtIG1lYW4oRWYxKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCkVmMiA8LSBhcHBseShzdWJzZXQoZHJhd3MzLCB2YXJpYWJsZT0nZjInKSwgMiwgbWVkaWFuKQpFZjIgPC0gZXhwKEVmMiAtIG1lYW4oRWYyKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCkVmX2RheV9vZl93ZWVrIDwtIGFwcGx5KHN1YnNldChkcmF3czMsIHZhcmlhYmxlPSdmX2RheV9vZl93ZWVrJyksIDIsIG1lZGlhbikKRWZfZGF5X29mX3dlZWsgPC0gZXhwKEVmX2RheV9vZl93ZWVrIC0gbWVhbihFZl9kYXlfb2Zfd2VlaykgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpwZiA8LSBkYXRhICU+JQogIG11dGF0ZShFZiA9IEVmKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9saW5lKGFlcyh5PUVmKSwgY29sb3I9c2V0MVsxXSwgYWxwaGE9MC43NSkgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMiKQpwZjEgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYxID0gRWYxKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9saW5lKGFlcyh5PUVmMSksIGNvbG9yPXNldDFbMV0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIikKcGYyIDwtIGRhdGEgJT4lCiAgbXV0YXRlKEVmMiA9IEVmMikgJT4lCiAgZ3JvdXBfYnkoZGF5X29mX3llYXIyKSAlPiUKICBzdW1tYXJpc2UobWVhbmJpcnRocz1tZWFuKGJpcnRoc19yZWxhdGl2ZTEwMCksIG1lYW5FZjI9bWVhbihFZjIpKSAlPiUKICBnZ3Bsb3QoYWVzKHg9YXMuRGF0ZSgiMTk4Ny0xMi0zMSIpK2RheV9vZl95ZWFyMiwgeT1tZWFuYmlydGhzKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKSArCiAgZ2VvbV9saW5lKGFlcyh5PW1lYW5FZjIpLCBjb2xvcj1zZXQxWzFdKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyBvZiB5ZWFyIikKcGYzIDwtIGdncGxvdChkYXRhPWRhdGEsIGFlcyh4PWRheV9vZl93ZWVrLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gMTo3LCBsYWJlbHM9YygnTW9uJywnVHVlJywnV2VkJywnVGh1JywnRnJpJywnU2F0JywnU3VuJykpICsKICBnZW9tX2xpbmUoZGF0YT1kYXRhLmZyYW1lKHg9MTo3LHk9RWZfZGF5X29mX3dlZWspLCBhZXMoeD14LCB5PUVmX2RheV9vZl93ZWVrKSwgY29sb3I9c2V0MVsxXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgb2Ygd2VlayIpCihwZiArIHBmMSkgLyAocGYyICsgcGYzKQoKIycgV2Vla2RheSBlZmZlY3RzIGFyZSBlYXN5IHRvIGVzdGltYXRlIGFzIHRoZXJlIGFyZSBhYm91dCB0aG91c2FuZAojJyBvYnNlcnZhdGlvbnMgcGVyIHdlZWtkYXkuCiMnIAoKIycgIyMjIE1vZGVsIDQ6IGxvbmcgdGVybSBzbW9vdGggKyBzZWFzb25hbCArIHdlZWtkYXkgd2l0aCBpbmNyZWFzaW5nIG1hZ25pdHVkZQojJwojJyBMb29raW5nIGF0IHRoZSB0aW1lIHNlcmllcyBvZiB3aG9sZSBkYXRhIHdlIHNlZSB0aGUgZG90cwojJyByZXByZXNlbnRpbmcgdGhlIGRhaWx5IHZhbHVlcyBmb3JtaW5nIHRocmVlIGJyYW5jaGVzIHRoYXQgYXJlCiMnIGdldHRpbmcgZnVydGhlciBhd2F5IGZyb20gZWFjaCBvdGhlci4gSW4gcHJldmlvdXMgYW5hbHlzaXMgKEJEQTMpCiMnIHdlIGFsc28gaGFkIGEgbW9kZWwgY29tcG9uZW50IGFsbG93aW5nIGdyYWR1YWxseSBjaGFuZ2luZyBlZmZlY3QKIycgZm9yIGRheSBvZiB3ZWVrIGFuZCBkaWQgb2JzZXJ2ZSB0aGF0IHRoZSBlZmZlY3Qgb2YgU2F0dXJkYXkgYW5kCiMnIFN1bmRheSBkaWQgZ2V0IHN0cm9uZ2VyIGluIHRpbWUuIFRoZSBuZXh0IG1vZGVsIGluY2x1ZGVzIHRpbWUKIycgZGVwZW5kZW50IG1hZ25pdHVkZSBjb21wb25lbnQgZm9yIHRoZSBkYXkgb2Ygd2VlayBlZmZlY3QuCiMnICQkCiMnIGYgPSBcbWJveHtpbnRlcmNlcHR9ICsgZl8xICsgZl8yICsgXGV4cChnXzMpXGJldGFfe1xtYm94e2RheSBvZiB3ZWVrfX0gXFwKIycgXG1ib3h7aW50ZXJjZXB0fSBcc2ltIFxtYm94e25vcm1hbH0oMCwxKVxcCiMnIGZfMSBcc2ltIFxtYm94e0dQfSgwLEtfMSlcXAojJyBmXzIgXHNpbSBcbWJveHtHUH0oMCxLXzIpXFwKIycgZ18zIFxzaW0gXG1ib3h7R1B9KDAsS18zKVxcCiMnIFxiZXRhX3tcbWJveHtkYXkgb2Ygd2Vla319ID0gMCBccXVhZCBcbWJveHtpZiBkYXkgb2Ygd2VlayBpcyBNb25kYXl9XFwKIycgXGJldGFfe1xtYm94e2RheSBvZiB3ZWVrfX0gXHNpbSBcbWJveHtub3JtYWx9KDAsMSkgXHF1YWQgXG1ib3h7aWYgZGF5IG9mIHdlZWsgaXMgbm90IE1vbmRheX0KIycgJCQKIycgVGhlIG1hZ25pdHVkZSBvZiB0aGUgd2Vla2RheSBlZmZlY3QgaXMgbW9kZWxsZWQgd2l0aCAkXGV4cChnXzMpJCwKIycgd2hlcmUgJGdfMyQgaGFzIEdQIHByaW9yIHdpdGggemVybyBtZWFuIGFuZCBleHBvbmVudGlhdGVkIHF1YWRyYXRpYwojJyBjb3ZhcmlhbmNlIGZ1bmN0aW9uLgojJyAKIycgQ29tcGlsZSBTdGFuIG1vZGVsIDQgW2dwYmY0LnN0YW5dKGh0dHBzOi8vZ2l0aHViLmNvbS9hdmVodGFyaS9jYXNlc3R1ZGllcy9ibG9iL21hc3Rlci9CaXJ0aGRheXMvZ3BiZjQuc3RhbikKIysgbW9kZWw0LCByZXN1bHRzPSdoaWRlJwptb2RlbDQgPC0gY21kc3Rhbl9tb2RlbChzdGFuX2ZpbGUgPSByb290KCJCaXJ0aGRheXMiLCAiZ3BiZjQuc3RhbiIpLAogICAgICAgICAgICAgICAgICAgICAgICBpbmNsdWRlX3BhdGhzID0gcm9vdCgiQmlydGhkYXlzIikpCgojJyBEYXRhIHRvIGJlIHBhc3NlZCB0byBTdGFuCnN0YW5kYXRhNCA8LSBsaXN0KHg9ZGF0YSRpZCwKICAgICAgICAgICAgICAgICAgeT1sb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApLAogICAgICAgICAgICAgICAgICBOPWxlbmd0aChkYXRhJGlkKSwKICAgICAgICAgICAgICAgICAgY19mMT0xLjUsICMgZmFjdG9yIGMgb2YgYmFzaXMgZnVuY3Rpb25zIGZvciBHUCBmb3IgZjEKICAgICAgICAgICAgICAgICAgTV9mMT0xMCwgICMgbnVtYmVyIG9mIGJhc2lzIGZ1bmN0aW9ucyBmb3IgR1AgZm9yIGYxCiAgICAgICAgICAgICAgICAgIEpfZjI9MjAsICAjIG51bWJlciBvZiBiYXNpcyBmdW5jdGlvbnMgZm9yIHBlcmlvZGljIGYyCiAgICAgICAgICAgICAgICAgIGNfZzM9MS41LCAjIGZhY3RvciBjIG9mIGJhc2lzIGZ1bmN0aW9ucyBmb3IgR1AgZm9yIGczCiAgICAgICAgICAgICAgICAgIE1fZzM9NSwgICAjIG51bWJlciBvZiBiYXNpcyBmdW5jdGlvbnMgZm9yIEdQIGZvciBnMwogICAgICAgICAgICAgICAgICBkYXlfb2Zfd2Vlaz1kYXRhJGRheV9vZl93ZWVrKSAKCiMnIEFzIHdlIGhhdmUgaW5jcmVhc2VkIHRoZSBjb21wbGV4aXR5IG9mIHRoZSBtb2RlbCwgdGhlIG1vZGUgc3RhcnRzCiMnIHRvIGJlIGxlc3MgYW5kIGxlc3MgcmVwcmVzZW50YXRpdmUgb2YgdGhlIHBvc3Rlcmlvci4gV2Ugc3RpbGwgdXNlCiMnIHRoZSBvcHRpbWl6YXRpb24gdG8gY2hlY2sgdGhhdCBjb2RlIHJldHVybnMgc29tZXRoaW5nIHJlYXNvbmFibGUKIycgYW5kIGFzIGluaXRpYWwgdmFsdWVzIGZvciBNQ01DLCBidXQgd2Ugbm93IHN0b3AgdGhlIG9wdGltaXphdGlvbgojJyBlYXJseS4gQnkgYWRkaW5nIGB0b2xfb2JqPTEwYCBhcmd1bWVudCwgdGhlIG9wdGltaXphdGlvbiBzdG9wcyB3aGVuCiMnIHRoZSBjaGFuZ2UgaW4gdGhlIGxvZyBwb3N0ZXJpb3IgZGVuc2l0eSBpcyBsZXNzIHRoYW4gMTAsIHdoaWNoIGlzCiMnIGxpa2VseSB0byBoYXBwZW5lZCBiZWZvcmUgcmVhY2hpbmcgdGhlIG1vZGUuCiMrIG9wdDQsIHJlc3VsdHM9J2hpZGUnCm9wdDQgPC0gbW9kZWw0JG9wdGltaXplKGRhdGE9c3RhbmRhdGE0LCBpbml0PTAsIGFsZ29yaXRobT0nYmZncycsIHRvbF9vYmo9MTApCgojJyBDaGVjayB3aGV0aGVyIHBhcmFtZXRlcnMgaGF2ZSByZWFzb25hYmxlIHZhbHVlcwpvZHJhd3M0IDwtIG9wdDQkZHJhd3MoKQpzdWJzZXQob2RyYXdzNCwgdmFyaWFibGU9YygnaW50ZXJjZXB0Jywnc2lnbWFfJywnbGVuZ3Roc2NhbGVfJywnc2lnbWEnKSwgcmVnZXg9VFJVRSkKc3Vic2V0KG9kcmF3czQsIHZhcmlhYmxlPWMoJ2JldGFfZjMnKSkKCiMnIENvbXBhcmUgdGhlIG1vZGVsIHRvIHRoZSBkYXRhCkVmIDwtIGV4cChhcy5udW1lcmljKHN1YnNldChvZHJhd3M0LCB2YXJpYWJsZT0nZicpKSkKRWYxIDwtIGFzLm51bWVyaWMoc3Vic2V0KG9kcmF3czQsIHZhcmlhYmxlPSdmMScpKQpFZjEgPC0gZXhwKEVmMSAtIG1lYW4oRWYxKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCkVmMiA8LSBhcy5udW1lcmljKHN1YnNldChvZHJhd3M0LCB2YXJpYWJsZT0nZjInKSkKRWYyIDwtIGV4cChFZjIgLSBtZWFuKEVmMikgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZl9kYXlfb2Zfd2VlayA8LSBhcy5udW1lcmljKHN1YnNldChvZHJhd3M0LCB2YXJpYWJsZT0nZl9kYXlfb2Zfd2VlaycpKQpFZl9kYXlfb2Zfd2VlayA8LSBleHAoRWZfZGF5X29mX3dlZWsgLSBtZWFuKEVmX2RheV9vZl93ZWVrKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCkVmMyA8LSBhcy5udW1lcmljKHN1YnNldChvZHJhd3M0LCB2YXJpYWJsZT0nZjMnKSkKRWYzIDwtIGV4cChFZjMgLSBtZWFuKEVmMykgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpwZiA8LSBkYXRhICU+JQogIG11dGF0ZShFZiA9IEVmKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9saW5lKGFlcyh5PUVmKSwgY29sb3I9c2V0MVsxXSwgYWxwaGE9MC43NSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMiKQpwZjEgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYxID0gRWYxKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9saW5lKGFlcyh5PUVmMSksIGNvbG9yPXNldDFbMV0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIikKcGYyIDwtIGRhdGEgJT4lCiAgbXV0YXRlKEVmMiA9IEVmMikgJT4lCiAgZ3JvdXBfYnkoZGF5X29mX3llYXIyKSAlPiUKICBzdW1tYXJpc2UobWVhbmJpcnRocz1tZWFuKGJpcnRoc19yZWxhdGl2ZTEwMCksIG1lYW5FZjI9bWVhbihFZjIpKSAlPiUKICBnZ3Bsb3QoYWVzKHg9YXMuRGF0ZSgiMTk4Ny0xMi0zMSIpK2RheV9vZl95ZWFyMiwgeT1tZWFuYmlydGhzKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKSArCiAgZ2VvbV9saW5lKGFlcyh5PW1lYW5FZjIpLCBjb2xvcj1zZXQxWzFdKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyBvZiB5ZWFyIikKcGYzIDwtIGdncGxvdChkYXRhPWRhdGEsIGFlcyh4PWRheV9vZl93ZWVrLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gMTo3LCBsYWJlbHM9YygnTW9uJywnVHVlJywnV2VkJywnVGh1JywnRnJpJywnU2F0JywnU3VuJykpICsKICBnZW9tX2xpbmUoZGF0YT1kYXRhLmZyYW1lKHg9MTo3LHk9RWZfZGF5X29mX3dlZWspLCBhZXMoeD14LCB5PUVmX2RheV9vZl93ZWVrKSwgY29sb3I9c2V0MVsxXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgb2Ygd2VlayIpCnBmM2IgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYzID0gRWYzKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDAvRWYxL0VmMioxMDAqMTAwKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIGdlb21fcG9pbnQoYWVzKHk9RWYzKSwgY29sb3I9c2V0MVsxXSwgc2l6ZT0wLjEpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIikKKHBmICsgcGYxKSAvIChwZjIgKyBwZjNiKQoKIycgU2FtcGxlIHNob3J0IGNoYWlucyB1c2luZyB0aGUgZWFybHkgc3RvcHBlZCBvcHRpbWl6YXRpb24gcmVzdWx0IGFzCiMnIGluaXRpYWwgdmFsdWVzIChhbHRob3VnaCB0aGUgcmVzdWx0IGZyb20gc2hvcnQgY2hhaW5zIGNhbiBiZSB1c2VmdWwKIycgaW4gYSBxdWljayB3b3JrZmxvdywgdGhlIHJlc3VsdCBzaG91bGQgbm90IGJlIHVzZWQgYXMgdGhlIGZpbmFsCiMnIHJlc3VsdCkuCmluaXQ0IDwtIHNhcHBseShjKCdpbnRlcmNlcHQwJywnbGVuZ3Roc2NhbGVfZjEnLCdsZW5ndGhzY2FsZV9mMicsJ2xlbmd0aHNjYWxlX2czJywKICAgICAgICAgICAgICAgICAgJ3NpZ21hX2YxJywnc2lnbWFfZjInLCdzaWdtYV9nMycsJ3NpZ21hJywKICAgICAgICAgICAgICAgICAgJ2JldGFfZjEnLCdiZXRhX2YyJywnYmV0YV9mMycsJ2JldGFfZzMnKSwKICAgICAgICAgICAgICAgIGZ1bmN0aW9uKHZhcmlhYmxlKSB7YXMubnVtZXJpYyhzdWJzZXQob2RyYXdzNCwgdmFyaWFibGU9dmFyaWFibGUpKX0pCiMrIGZpdDQsIHJlc3VsdHM9J2hpZGUnCmZpdDQgPC0gbW9kZWw0JHNhbXBsZShkYXRhPXN0YW5kYXRhNCwgaXRlcl93YXJtdXA9MTAwLCBpdGVyX3NhbXBsaW5nPTEwMCwKICAgICAgICAgICAgICAgICAgICAgIGNoYWlucz00LCBwYXJhbGxlbF9jaGFpbnM9NCwKICAgICAgICAgICAgICAgICAgICAgIGluaXQ9ZnVuY3Rpb24oKSB7IGluaXQ0IH0sIHJlZnJlc2g9MTApCgojJyBDaGVjayB3aGV0aGVyIHBhcmFtZXRlcnMgaGF2ZSByZWFzb25hYmxlIHZhbHVlcwpkcmF3czQgPC0gZml0NCRkcmF3cygpCnN1bW1hcmlzZV9kcmF3cyhzdWJzZXQoZHJhd3M0LCB2YXJpYWJsZT1jKCdpbnRlcmNlcHQnLCdzaWdtYV8nLCdsZW5ndGhzY2FsZV8nLCdzaWdtYScpLCByZWdleD1UUlVFKSkKc3VtbWFyaXNlX2RyYXdzKHN1YnNldChkcmF3czQsIHZhcmlhYmxlPWMoJ2JldGFfZjMnKSkpCgojJyBDb21wYXJlIHRoZSBtb2RlbCB0byB0aGUgZGF0YQpkcmF3czQgPC0gYXNfZHJhd3NfbWF0cml4KGRyYXdzNCkKRWYgPC0gZXhwKGFwcGx5KHN1YnNldChkcmF3czQsIHZhcmlhYmxlPSdmJyksIDIsIG1lZGlhbikpCkVmMSA8LSBhcHBseShzdWJzZXQoZHJhd3M0LCB2YXJpYWJsZT0nZjEnKSwgMiwgbWVkaWFuKQpFZjEgPC0gZXhwKEVmMSAtIG1lYW4oRWYxKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCkVmMiA8LSBhcHBseShzdWJzZXQoZHJhd3M0LCB2YXJpYWJsZT0nZjInKSwgMiwgbWVkaWFuKQpFZjIgPC0gZXhwKEVmMiAtIG1lYW4oRWYyKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCkVmX2RheV9vZl93ZWVrIDwtIGFwcGx5KHN1YnNldChkcmF3czQsIHZhcmlhYmxlPSdmX2RheV9vZl93ZWVrJyksIDIsIG1lZGlhbikKRWZfZGF5X29mX3dlZWsgPC0gZXhwKEVmX2RheV9vZl93ZWVrIC0gbWVhbihFZl9kYXlfb2Zfd2VlaykgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZjMgPC0gYXBwbHkoc3Vic2V0KGRyYXdzNCwgdmFyaWFibGU9J2YzJyksIDIsIG1lZGlhbikKRWYzIDwtIGV4cChFZjMgLSBtZWFuKEVmMykgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpwZiA8LSBkYXRhICU+JQogIG11dGF0ZShFZiA9IEVmKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9saW5lKGFlcyh5PUVmKSwgY29sb3I9c2V0MVsxXSwgYWxwaGE9MC43NSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMiKQpwZjEgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYxID0gRWYxKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9saW5lKGFlcyh5PUVmMSksIGNvbG9yPXNldDFbMV0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIikKcGYyIDwtIGRhdGEgJT4lCiAgbXV0YXRlKEVmMiA9IEVmMikgJT4lCiAgZ3JvdXBfYnkoZGF5X29mX3llYXIyKSAlPiUKICBzdW1tYXJpc2UobWVhbmJpcnRocz1tZWFuKGJpcnRoc19yZWxhdGl2ZTEwMCksIG1lYW5FZjI9bWVhbihFZjIpKSAlPiUKICBnZ3Bsb3QoYWVzKHg9YXMuRGF0ZSgiMTk4Ny0xMi0zMSIpK2RheV9vZl95ZWFyMiwgeT1tZWFuYmlydGhzKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKSArCiAgZ2VvbV9saW5lKGFlcyh5PW1lYW5FZjIpLCBjb2xvcj1zZXQxWzFdKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyBvZiB5ZWFyIikKcGYzIDwtIGdncGxvdChkYXRhPWRhdGEsIGFlcyh4PWRheV9vZl93ZWVrLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gMTo3LCBsYWJlbHM9YygnTW9uJywnVHVlJywnV2VkJywnVGh1JywnRnJpJywnU2F0JywnU3VuJykpICsKICBnZW9tX2xpbmUoZGF0YT1kYXRhLmZyYW1lKHg9MTo3LHk9RWZfZGF5X29mX3dlZWspLCBhZXMoeD14LCB5PUVmX2RheV9vZl93ZWVrKSwgY29sb3I9c2V0MVsxXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgb2Ygd2VlayIpCnBmM2IgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYzID0gRWYzKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDAvRWYxL0VmMioxMDAqMTAwKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIGdlb21fcG9pbnQoYWVzKHk9RWYzKSwgY29sb3I9c2V0MVsxXSwgc2l6ZT0wLjEpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIikKKHBmICsgcGYxKSAvIChwZjIgKyBwZjNiKQoKIycgVGhlIG1vZGVsIGZpdHMgd2VsbCB0aGUgZGlmZmVyZW50IGJyYW5jaGVzIHZpc2libGUgaW4gcGxvdHRlZCBkYWlseQojJyByZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzLCB0aGF0IGlzLCBpdCBpcyBhYmxlIHRvIG1vZGVsIHRoZQojJyBpbmNyZWFzaW5nIHdlZWtlbmQgZWZmZWN0LgojJyAKCiMnICMjIyBNb2RlbCA1OiBsb25nIHRlcm0gc21vb3RoICsgc2Vhc29uYWwgKyB3ZWVrZGF5IHdpdGggdGltZSBkZXBlbmRlbnQgbWFnbml0dWRlICsgZGF5IG9mIHllYXIgUkhTCiMnCiMnIFRoZSBuZXh0IGNvbXBvbmVudCB0byBhZGQgaXMgZGF5IG9mIHllYXIgZWZmZWN0LiBNYW55IGJhbmsgaG9saWRheXMKIycgYXJlIGV2ZXJ5IHllYXIgb24gdGhlIHNhbWUgZGF5IG9mIHllYXIgYW5kIHRoZXJlIG1pZ2h0IGJlIGFsc28KIycgb3RoZXIgc3BlY2lhbCBkYXlzIHRoYXQgYXJlIGZhdm9yZWQgb3IgZGlzZmF2b3JlZC4KIycKIycgJCQKIycgZiA9IFxtYm94e2ludGVyY2VwdH0gKyBmXzEgKyBmXzIgKyBcZXhwKGdfMylcYmV0YV97XG1ib3h7ZGF5IG9mIHdlZWt9fSArIFxiZXRhX3tcbWJveHtkYXkgb2YgeWVhcn19XFwKIycgXG1ib3h7aW50ZXJjZXB0fSBcc2ltIFxtYm94e25vcm1hbH0oMCwxKVxcCiMnIGZfMSBcc2ltIFxtYm94e0dQfSgwLEtfMSlcXAojJyBmXzIgXHNpbSBcbWJveHtHUH0oMCxLXzIpXFwKIycgZ18zIFxzaW0gXG1ib3h7R1B9KDAsS18zKVxcCiMnIFxiZXRhX3tcbWJveHtkYXkgb2Ygd2Vla319ID0gMCBccXVhZCBcbWJveHtpZiBkYXkgb2Ygd2VlayBpcyBNb25kYXl9XFwKIycgXGJldGFfe1xtYm94e2RheSBvZiB3ZWVrfX0gXHNpbSBcbWJveHtub3JtYWx9KDAsMSkgXHF1YWQgXG1ib3h7aWYgZGF5IG9mIHdlZWsgaXMgbm90IE1vbmRheX1cXAojJyBcYmV0YV97XG1ib3h7ZGF5IG9mIHllYXJ9fSBcc2ltIFJIUygwLDAuMSkKIycgJCQKIycgQXMgd2UgYXNzdW1lIHRoYXQgb25seSBzb21lIGRheXMgb2YgeWVhciBhcmUgc3BlY2lhbCwgd2UgdXNlCiMnIHJlZ3VsYXJpemVkIGhvcnNlc2hvZSAoUkhTKSBwcmlvciBmb3IgZGF5IG9mIHllYXIgZWZmZWN0cy4KIycKIycgQXQgdGhpcyBwb2ludCB0aGUgb3B0aW1pemF0aW9uIGRpZG4ndCBwcm9kdWNlIHJlYXNvbmFibGUgcmVzdWx0IGFzCiMnIGVhcmxpZXIgYW5kIHNhbXBsaW5nIHR1cm5lZCBvdXQgdG8gYmUgdmVyeSBzbG93LiBXZSBhc3N1bWVkIHRoZQojJyBvcHRpbWl6YXRpb24gZmFpbHMgYmVjYXVzZSB0aGVyZSB3ZXJlIHNvIG1hbnkgbW9yZSBwYXJhbWV0ZXJzIHdpdGgKIycgaGllcmFyY2hpY2FsIHByaW9yLiBBcyBldmVuIHRoZSBzaG9ydCBjaGFpbiBzYW1wbGluZyB3b3VsZCBoYXZlCiMnIHRha2VuIG1vcmUgdGhhbiBob3VyLCBpdCB3b3VsZCBoYXZlIGJlZW4gdGltZSBjb25zdW1pbmcgdG8gZnVydGhlcgojJyB0byB0ZXN0IHRoZSBtb2RlbC4gQXMgcGFydCBvZiB0aGUgcXVpY2sgaXRlcmF0aXZlIG1vZGVsIGJ1aWxkaW5nIGl0CiMnIHdhcyBiZXR0ZXIgdG8gZ2l2ZSB1cCBvbiB0aGlzIG1vZGVsIGZvciBhIG1vbWVudC4KIycKIycgQ29tcGlsZSBTdGFuIG1vZGVsIDUgW2dwYmY1LnN0YW5dKGh0dHBzOi8vZ2l0aHViLmNvbS9hdmVodGFyaS9jYXNlc3R1ZGllcy9ibG9iL21hc3Rlci9CaXJ0aGRheXMvZ3BiZjUuc3RhbikKIysgbW9kZWw1LCByZXN1bHRzPSdoaWRlJwptb2RlbDUgPC0gY21kc3Rhbl9tb2RlbChzdGFuX2ZpbGUgPSByb290KCJCaXJ0aGRheXMiLCAiZ3BiZjUuc3RhbiIpLAogICAgICAgICAgICAgICAgICAgICAgICBpbmNsdWRlX3BhdGhzID0gcm9vdCgiQmlydGhkYXlzIikpCgojJyBEYXRhIHRvIGJlIHBhc3NlZCB0byBTdGFuCnN0YW5kYXRhNSA8LSBsaXN0KHg9ZGF0YSRpZCwKICAgICAgICAgICAgICAgICAgeT1sb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApLAogICAgICAgICAgICAgICAgICBOPWxlbmd0aChkYXRhJGlkKSwKICAgICAgICAgICAgICAgICAgY19mMT0xLjUsICMgZmFjdG9yIGMgb2YgYmFzaXMgZnVuY3Rpb25zIGZvciBHUCBmb3IgZjEKICAgICAgICAgICAgICAgICAgTV9mMT0xMCwgICMgbnVtYmVyIG9mIGJhc2lzIGZ1bmN0aW9ucyBmb3IgR1AgZm9yIGYxCiAgICAgICAgICAgICAgICAgIEpfZjI9MjAsICAjIG51bWJlciBvZiBiYXNpcyBmdW5jdGlvbnMgZm9yIHBlcmlvZGljIGYyCiAgICAgICAgICAgICAgICAgIGNfZzM9MS41LCAjIGZhY3RvciBjIG9mIGJhc2lzIGZ1bmN0aW9ucyBmb3IgR1AgZm9yIGczCiAgICAgICAgICAgICAgICAgIE1fZzM9NSwgICAjIG51bWJlciBvZiBiYXNpcyBmdW5jdGlvbnMgZm9yIEdQIGZvciBnMwogICAgICAgICAgICAgICAgICBzY2FsZV9nbG9iYWw9MC4xLCAjIGdsb3ZhbCBzY2FsZSBmb3IgUkhTIHByaW9yCiAgICAgICAgICAgICAgICAgIGRheV9vZl93ZWVrPWRhdGEkZGF5X29mX3dlZWssCiAgICAgICAgICAgICAgICAgIGRheV9vZl95ZWFyPWRhdGEkZGF5X29mX3llYXIyKSAjIDFzdCBNYXJjaCA9IDYxIGV2ZXJ5IHllYXIKCiMnIE9wdGltaXppbmcgaXMgZmFzdGVyIHRoYW4gc2FtcGxpbmcgKGFsdGhvdWdoIHRoaXMgcmVzdWx0IGNhbiBiZQojJyB1c2VmdWwgaW4gYSBxdWljayB3b3JrZmxvdywgdGhlIHJlc3VsdCBzaG91bGQgbm90IGJlIHVzZWQgYXMgdGhlCiMnIGZpbmFsIHJlc3VsdCkuCiMrIG9wdDUsIHJlc3VsdHM9J2hpZGUnCm9wdDUgPC0gbW9kZWw1JG9wdGltaXplKGRhdGE9c3RhbmRhdGE1LCBpbml0PTAsIGFsZ29yaXRobT0nbGJmZ3MnLAogICAgICAgICAgICAgICAgICAgICAgICBoaXN0b3J5PTEwMCwgdG9sX29iaj0xMCkKCiMnIENoZWNrIHdoZXRoZXIgcGFyYW1ldGVycyBoYXZlIHJlYXNvbmFibGUgdmFsdWVzCm9kcmF3czUgPC0gb3B0NSRkcmF3cygpCnN1YnNldChvZHJhd3M1LCB2YXJpYWJsZT1jKCdpbnRlcmNlcHQwJywnc2lnbWFfJywnbGVuZ3Roc2NhbGVfJywnc2lnbWEnKSwgcmVnZXg9VFJVRSkKc3Vic2V0KG9kcmF3czUsIHZhcmlhYmxlPWMoJ2JldGFfZjMnKSkKRWY0IDwtIGFzLm51bWVyaWMoc3Vic2V0KG9kcmF3czUsIHZhcmlhYmxlPSdiZXRhX2Y0JykpKnNkKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpCkVmNCA8LSBleHAoRWY0KSoxMDAKZGF0YS5mcmFtZSh4PWFzLkRhdGUoIjE5ODgtMDEtMDEiKSswOjM2NSwgeT1FZjQpICU+JQogIGdncGxvdChhZXMoeD14LHk9eSkpICsgZ2VvbV9saW5lKGNvbG9yPXNldDFbMV0pICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgb2YgeWVhciIpCgojJyBDb21wYXJlIHRoZSBtb2RlbCB0byB0aGUgZGF0YQpFZiA8LSBleHAoYXMubnVtZXJpYyhzdWJzZXQob2RyYXdzNSwgdmFyaWFibGU9J2YnKSkpCkVmMSA8LSBhcy5udW1lcmljKHN1YnNldChvZHJhd3M1LCB2YXJpYWJsZT0nZjEnKSkKRWYxIDwtIGV4cChFZjEgLSBtZWFuKEVmMSkgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZjIgPC0gYXMubnVtZXJpYyhzdWJzZXQob2RyYXdzNSwgdmFyaWFibGU9J2YyJykpCkVmMiA8LSBleHAoRWYyIC0gbWVhbihFZjIpICsgbWVhbihsb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApKSkKRWZfZGF5X29mX3dlZWsgPC0gYXMubnVtZXJpYyhzdWJzZXQob2RyYXdzNSwgdmFyaWFibGU9J2ZfZGF5X29mX3dlZWsnKSkKRWZfZGF5X29mX3dlZWsgPC0gZXhwKEVmX2RheV9vZl93ZWVrIC0gbWVhbihFZl9kYXlfb2Zfd2VlaykgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZjQgPC0gYXMubnVtZXJpYyhzdWJzZXQob2RyYXdzNSwgdmFyaWFibGU9J2JldGFfZjQnKSkqc2QobG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkKRWY0IDwtIGV4cChFZjQpKjEwMApwZiA8LSBkYXRhICU+JQogIG11dGF0ZShFZiA9IEVmKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9saW5lKGFlcyh5PUVmKSwgY29sb3I9c2V0MVsxXSwgYWxwaGE9MC43NSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMiKQpwZjEgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYxID0gRWYxKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9saW5lKGFlcyh5PUVmMSksIGNvbG9yPXNldDFbMV0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIikKcGYyIDwtIGRhdGEgJT4lCiAgbXV0YXRlKEVmMiA9IEVmMikgJT4lCiAgZ3JvdXBfYnkoZGF5X29mX3llYXIyKSAlPiUKICBzdW1tYXJpc2UobWVhbmJpcnRocz1tZWFuKGJpcnRoc19yZWxhdGl2ZTEwMCksIG1lYW5FZjI9bWVhbihFZjIpKSAlPiUKICBnZ3Bsb3QoYWVzKHg9YXMuRGF0ZSgiMTk4Ny0xMi0zMSIpK2RheV9vZl95ZWFyMiwgeT1tZWFuYmlydGhzKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKSArCiAgZ2VvbV9saW5lKGFlcyh5PW1lYW5FZjIpLCBjb2xvcj1zZXQxWzFdKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyBvZiB5ZWFyIikKcGYzIDwtIGdncGxvdChkYXRhPWRhdGEsIGFlcyh4PWRheV9vZl93ZWVrLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gMTo3LCBsYWJlbHM9YygnTW9uJywnVHVlJywnV2VkJywnVGh1JywnRnJpJywnU2F0JywnU3VuJykpICsKICBnZW9tX2xpbmUoZGF0YT1kYXRhLmZyYW1lKHg9MTo3LHk9RWZfZGF5X29mX3dlZWspLCBhZXMoeD14LCB5PUVmX2RheV9vZl93ZWVrKSwgY29sb3I9c2V0MVsxXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgb2Ygd2VlayIpCnBmMmIgPC1kYXRhLmZyYW1lKHg9YXMuRGF0ZSgiMTk1OS0xMi0zMSIpKzE6MzY2LCB5PUVmNCkgJT4lCiAgZ2dwbG90KGFlcyh4PXgseT15KSkgKyBnZW9tX2xpbmUoY29sb3I9c2V0MVsxXSkgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyBvZiB5ZWFyIikKKHBmICsgcGYxKSAvIChwZjIgKyBwZjMpIC8gKHBmMmIpCgojJyBUaGUgcXVpY2sgbW9kZWwgZml0IGZvciBtb2RlbCA1IGlzIG5vdCBnb29kLCBidXQgYXMgdGhlIHNhbXBsaW5nCiMnIHdhcyB2ZXJ5IHNsb3cgaXQgd2Fzbid0IGVhc3kgdG8gZmlndXJlIG91dCB3aGF0IGlzIGdvaW5nIHdyb25nLgojJyAKCiMnICMjIyBNb2RlbCA2OiBsb25nIHRlcm0gc21vb3RoICsgc2Vhc29uYWwgKyB3ZWVrZGF5ICsgZGF5IG9mIHllYXIKIycKIycgVG8gc2ltcGxpZnkgdGhlIGFuYWx5c2lzIG9mIHRoZSBkYXkgb2YgeWVhciBlZmZlY3QgYW5kIG1ha2UgdGhlCiMnIGluZmVyZW5jZSBkdXJpbmcgdGhlIGV4cGxvcmF0aW9uIGZhc3Rlciwgd2UgZHJvcCB0aGUgdGltZSBkZXBlbmRlbnQKIycgZGF5IG9mIHdlZWsgZWZmZWN0IGFuZCBSSFMgZm9yIGEgbW9tZW50IGFuZCB1c2Ugbm9ybWFsIHByaW9yIGZvcgojJyB0aGUgZGF5IG9mIHllYXIgZWZmZWN0LgojJwojJyAkJAojJyBmID0gXG1ib3h7aW50ZXJjZXB0fSArIGZfMSArIGZfMiArIFxiZXRhX3tcbWJveHtkYXkgb2Ygd2Vla319ICsgXGJldGFfe1xtYm94e2RheSBvZiB5ZWFyfX1cXAojJyBcbWJveHtpbnRlcmNlcHR9IFxzaW0gXG1ib3h7bm9ybWFsfSgwLDEpXFwKIycgZl8xIFxzaW0gXG1ib3h7R1B9KDAsS18xKVxcCiMnIGZfMiBcc2ltIFxtYm94e0dQfSgwLEtfMilcXAojJyBnXzMgXHNpbSBcbWJveHtHUH0oMCxLXzMpXFwKIycgXGJldGFfe1xtYm94e2RheSBvZiB3ZWVrfX0gPSAwIFxxdWFkIFxtYm94e2lmIGRheSBvZiB3ZWVrIGlzIE1vbmRheX1cXAojJyBcYmV0YV97XG1ib3h7ZGF5IG9mIHdlZWt9fSBcc2ltIFxtYm94e25vcm1hbH0oMCwxKSBccXVhZCBcbWJveHtpZiBkYXkgb2Ygd2VlayBpcyBub3QgTW9uZGF5fVxcCiMnIFxiZXRhX3tcbWJveHtkYXkgb2YgeWVhcn19IFxzaW0gXG1ib3h7bm9ybWFsfSgwLDAuMSkKIycgJCQKIycgCiMnIENvbXBpbGUgU3RhbiBtb2RlbCA2IFtncGJmNi5zdGFuXShodHRwczovL2dpdGh1Yi5jb20vYXZlaHRhcmkvY2FzZXN0dWRpZXMvYmxvYi9tYXN0ZXIvQmlydGhkYXlzL2dwYmY2LnN0YW4pCiMrIG1vZGVsNiwgcmVzdWx0cz0naGlkZScKbW9kZWw2IDwtIGNtZHN0YW5fbW9kZWwoc3Rhbl9maWxlID0gcm9vdCgiQmlydGhkYXlzIiwgImdwYmY2LnN0YW4iKSwKICAgICAgICAgICAgICAgICAgICAgICAgaW5jbHVkZV9wYXRocyA9IHJvb3QoIkJpcnRoZGF5cyIpKQoKIycgRGF0YSB0byBiZSBwYXNzZWQgdG8gU3RhbgpzdGFuZGF0YTYgPC0gbGlzdCh4PWRhdGEkaWQsCiAgICAgICAgICAgICAgICAgIHk9bG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSwKICAgICAgICAgICAgICAgICAgTj1sZW5ndGgoZGF0YSRpZCksCiAgICAgICAgICAgICAgICAgIGNfZjE9MS41LCAjIGZhY3RvciBjIG9mIGJhc2lzIGZ1bmN0aW9ucyBmb3IgR1AgZm9yIGYxCiAgICAgICAgICAgICAgICAgIE1fZjE9MTAsICMgbnVtYmVyIG9mIGJhc2lzIGZ1bmN0aW9ucyBmb3IgR1AgZm9yIGYxCiAgICAgICAgICAgICAgICAgIEpfZjI9MjAsICMgbnVtYmVyIG9mIGJhc2lzIGZ1bmN0aW9ucyBmb3IgcGVyaW9kaWMgZjIKICAgICAgICAgICAgICAgICAgZGF5X29mX3dlZWs9ZGF0YSRkYXlfb2Zfd2VlaywKICAgICAgICAgICAgICAgICAgZGF5X29mX3llYXI9ZGF0YSRkYXlfb2ZfeWVhcjIpICMgMXN0IE1hcmNoID0gNjEgZXZlcnkgeWVhcgoKIycgT3B0aW1pemluZyBpcyBmYXN0ZXIgdGhhbiBzYW1wbGluZyAoYWx0aG91Z2ggdGhpcyByZXN1bHQgY2FuIGJlCiMnIHVzZWZ1bCBpbiBhIHF1aWNrIHdvcmtmbG93LCB0aGUgcmVzdWx0IHNob3VsZCBub3QgYmUgdXNlZCBhcyB0aGUKIycgZmluYWwgcmVzdWx0KS4KIysgb3B0NiwgcmVzdWx0cz0naGlkZScKb3B0NiA8LSBtb2RlbDYkb3B0aW1pemUoZGF0YT1zdGFuZGF0YTYsIGluaXQ9MCwgYWxnb3JpdGhtPSdsYmZncycsCiAgICAgICAgICAgICAgICAgICAgICAgIGhpc3Rvcnk9MTAwLCB0b2xfb2JqPTEwKQoKIycgQ2hlY2sgd2hldGhlciBwYXJhbWV0ZXJzIGhhdmUgcmVhc29uYWJsZSB2YWx1ZXMKb2RyYXdzNiA8LSBvcHQ2JGRyYXdzKCkKc3Vic2V0KG9kcmF3czYsIHZhcmlhYmxlPWMoJ2ludGVyY2VwdCcsJ3NpZ21hXycsJ2xlbmd0aHNjYWxlXycsJ3NpZ21hJyksIHJlZ2V4PVRSVUUpCnN1YnNldChvZHJhd3M2LCB2YXJpYWJsZT1jKCdiZXRhX2YzJykpCkVmNCA8LSBhcy5udW1lcmljKHN1YnNldChvZHJhd3M2LCB2YXJpYWJsZT0nYmV0YV9mNCcpKSpzZChsb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApKQpFZjQgPC0gZXhwKEVmNCkqMTAwCmRhdGEuZnJhbWUoeD1hcy5EYXRlKCIxOTg4LTAxLTAxIikrMDozNjUsIHk9RWY0KSAlPiUKICBnZ3Bsb3QoYWVzKHg9eCx5PXkpKSArIGdlb21fbGluZShjb2xvcj1zZXQxWzFdKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCBkYXRlX2xhYmVscyA9ICIlYiIpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIG9mIHllYXIiKQojJyBXZSByZWNvZ25pemUgc29tZSBmYW1pbGlhciBzdHJ1Y3R1cmUgaW4gdGhlIGRheSBvZiB5ZWFyIGVmZmVjdCBhbmQKIycgcHJvY2VlZCB0byBzYW1wbGluZy4KCiMnIFNhbXBsZSBzaG9ydCBjaGFpbnMgdXNpbmcgdGhlIGVhcmx5IHN0b3BwZWQgb3B0aW1pemF0aW9uIHJlc3VsdCBhcwojJyBpbml0aWFsIHZhbHVlcyAoYWx0aG91Z2ggdGhlIHJlc3VsdCBmcm9tIHNob3J0IGNoYWlucyBjYW4gYmUgdXNlZnVsCiMnIGluIGEgcXVpY2sgd29ya2Zsb3csIHRoZSByZXN1bHQgc2hvdWxkIG5vdCBiZSB1c2VkIGFzIHRoZSBmaW5hbAojJyByZXN1bHQpLgppbml0NiA8LSBzYXBwbHkoYygnaW50ZXJjZXB0MCcsJ2xlbmd0aHNjYWxlX2YxJywnbGVuZ3Roc2NhbGVfZjInLAogICAgICAgICAgICAgICAgICAnc2lnbWFfZjEnLCdzaWdtYV9mMicsJ3NpZ21hX2Y0Jywnc2lnbWEnLAogICAgICAgICAgICAgICAgICAnYmV0YV9mMScsJ2JldGFfZjInLCdiZXRhX2YzJywnYmV0YV9mNCcpLAogICAgICAgICAgICAgICAgZnVuY3Rpb24odmFyaWFibGUpIHthcy5udW1lcmljKHN1YnNldChvZHJhd3M2LCB2YXJpYWJsZT12YXJpYWJsZSkpfSkKIysgZml0NiwgcmVzdWx0cz0naGlkZScKZml0NiA8LSBtb2RlbDYkc2FtcGxlKGRhdGE9c3RhbmRhdGE2LCBpdGVyX3dhcm11cD0xMDAsIGl0ZXJfc2FtcGxpbmc9MTAwLAogICAgICAgICAgICAgICAgICAgICAgY2hhaW5zPTQsIHBhcmFsbGVsX2NoYWlucz00LAogICAgICAgICAgICAgICAgICAgICAgaW5pdD1mdW5jdGlvbigpIHsgaW5pdDYgfSkKCiMnIENoZWNrIHdoZXRoZXIgcGFyYW1ldGVycyBoYXZlIHJlYXNvbmFibGUgdmFsdWVzCmRyYXdzNiA8LSBmaXQ2JGRyYXdzKCkKc3VtbWFyaXNlX2RyYXdzKHN1YnNldChkcmF3czYsIHZhcmlhYmxlPWMoJ2ludGVyY2VwdCcsJ3NpZ21hXycsJ2xlbmd0aHNjYWxlXycsJ3NpZ21hJyksIHJlZ2V4PVRSVUUpKQpzdW1tYXJpc2VfZHJhd3Moc3Vic2V0KGRyYXdzNiwgdmFyaWFibGU9YygnYmV0YV9mMycpKSkKZHJhd3M2IDwtIGFzX2RyYXdzX21hdHJpeChkcmF3czYpCkVmNCA8LSBhcHBseShzdWJzZXQoZHJhd3M2LCB2YXJpYWJsZT0nYmV0YV9mNCcpLCAyLCBtZWRpYW4pKnNkKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpCkVmNCA8LSBleHAoRWY0KSoxMDAKZGF0YS5mcmFtZSh4PWFzLkRhdGUoIjE5ODgtMDEtMDEiKSswOjM2NSwgeT1FZjQpICU+JQogIGdncGxvdChhZXMoeD14LHk9eSkpICsgZ2VvbV9saW5lKGNvbG9yPXNldDFbMV0pICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgb2YgeWVhciIpCgojJyBDb21wYXJlIHRoZSBtb2RlbCB0byB0aGUgZGF0YQpkcmF3czYgPC0gYXNfZHJhd3NfbWF0cml4KGRyYXdzNikKRWYgPC0gZXhwKGFwcGx5KHN1YnNldChkcmF3czYsIHZhcmlhYmxlPSdmJyksIDIsIG1lZGlhbikpCkVmMSA8LSBhcHBseShzdWJzZXQoZHJhd3M2LCB2YXJpYWJsZT0nZjEnKSwgMiwgbWVkaWFuKQpFZjEgPC0gZXhwKEVmMSAtIG1lYW4oRWYxKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCkVmMiA8LSBhcHBseShzdWJzZXQoZHJhd3M2LCB2YXJpYWJsZT0nZjInKSwgMiwgbWVkaWFuKQpFZjIgPC0gZXhwKEVmMiAtIG1lYW4oRWYyKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCkVmX2RheV9vZl93ZWVrIDwtIGFwcGx5KHN1YnNldChkcmF3czYsIHZhcmlhYmxlPSdmX2RheV9vZl93ZWVrJyksIDIsIG1lZGlhbikKRWZfZGF5X29mX3dlZWsgPC0gZXhwKEVmX2RheV9vZl93ZWVrIC0gbWVhbihFZl9kYXlfb2Zfd2VlaykgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZjQgPC0gYXBwbHkoc3Vic2V0KGRyYXdzNiwgdmFyaWFibGU9J2JldGFfZjQnKSwgMiwgbWVkaWFuKSpzZChsb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApKQpFZjQgPC0gZXhwKEVmNCkqMTAwCnBmIDwtIGRhdGEgJT4lCiAgbXV0YXRlKEVmID0gRWYpICU+JQogIGdncGxvdChhZXMoeD1kYXRlLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBnZW9tX2xpbmUoYWVzKHk9RWYpLCBjb2xvcj1zZXQxWzFdLCBhbHBoYT0wLjc1KSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyIpCnBmMSA8LSBkYXRhICU+JQogIG11dGF0ZShFZjEgPSBFZjEpICU+JQogIGdncGxvdChhZXMoeD1kYXRlLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBnZW9tX2xpbmUoYWVzKHk9RWYxKSwgY29sb3I9c2V0MVsxXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMiKQpwZjIgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYyID0gRWYyKSAlPiUKICBncm91cF9ieShkYXlfb2ZfeWVhcjIpICU+JQogIHN1bW1hcmlzZShtZWFuYmlydGhzPW1lYW4oYmlydGhzX3JlbGF0aXZlMTAwKSwgbWVhbkVmMj1tZWFuKEVmMikpICU+JQogIGdncGxvdChhZXMoeD1hcy5EYXRlKCIxOTg3LTEyLTMxIikrZGF5X29mX3llYXIyLCB5PW1lYW5iaXJ0aHMpKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCBkYXRlX2xhYmVscyA9ICIlYiIpICsKICBnZW9tX2xpbmUoYWVzKHk9bWVhbkVmMiksIGNvbG9yPXNldDFbMV0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIG9mIHllYXIiKQpwZjMgPC0gZ2dwbG90KGRhdGE9ZGF0YSwgYWVzKHg9ZGF5X29mX3dlZWssIHk9YmlydGhzX3JlbGF0aXZlMTAwKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSAxOjcsIGxhYmVscz1jKCdNb24nLCdUdWUnLCdXZWQnLCdUaHUnLCdGcmknLCdTYXQnLCdTdW4nKSkgKwogIGdlb21fbGluZShkYXRhPWRhdGEuZnJhbWUoeD0xOjcseT1FZl9kYXlfb2Zfd2VlayksIGFlcyh4PXgsIHk9RWZfZGF5X29mX3dlZWspLCBjb2xvcj1zZXQxWzFdKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyBvZiB3ZWVrIikKZjEzIDwtIGRhdGEgJT4lIGZpbHRlcih5ZWFyPT0xOTg4KSU+JXNlbGVjdChkYXksZGF0ZSklPiVtdXRhdGUoeT1FZjQpJT4lZmlsdGVyKGRheT09MTMpCnBmMmIgPC1kYXRhLmZyYW1lKHg9YXMuRGF0ZSgiMTk4OC0wMS0wMSIpKzA6MzY1LCB5PUVmNCkgJT4lCiAgZ2dwbG90KGFlcyh4PXgseT15KSkgKyBnZW9tX2xpbmUoY29sb3I9c2V0MVsxXSkgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyBvZiB5ZWFyIikgKwogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMDEtMDEiKSx5PUVmNFsxXS0xLGxhYmVsPSJOZXcgeWVhciIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTAyLTE0IikseT1FZjRbNDVdKzEuNSxsYWJlbD0iVmFsZW50aW5lJ3MgZGF5IikgKwogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMDItMjkiKSx5PUVmNFs2MF0tMi41LGxhYmVsPSJMZWFwIGRheSIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTA0LTAxIikseT1FZjRbOTJdLTEuNSxsYWJlbD0iQXByaWwgMXN0IikgKyAKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTA3LTA0IikseT1FZjRbMTg2XS0xLjUsbGFiZWw9IkluZGVwZW5kZW5jZSBkYXkiKSArCiAgYW5ub3RhdGUoInRleHQiLHg9YXMuRGF0ZSgiMTk4OC0xMC0zMSIpLHk9RWY0WzMwNV0tMS41LGxhYmVsPSJIYWxsb3dlZW4iKSArIAogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMTItMjQiKSx5PUVmNFszNjBdLTEuNSxsYWJlbD0iQ2hyaXN0bWFzIikgKwogIGdlb21fcG9pbnQoZGF0YT1mMTMsYWVzKHg9ZGF0ZSx5PXkpLCBzaXplPTMsIHNoYXBlPTEpCihwZiArIHBmMSkgLyAocGYyICsgcGYzKSAvIHBmMmIKCiMnIFRoZSBzaG9ydCBzYW1wbGluZyByZXN1bHQgbG9va3MgcmVhc29uYWJsZSBhbmQgdGh1cyB0aGUgcHJvYmxlbSBpcwojJyBub3QgaW4gYWRkaW5nIHRoZSBkYXkgb2YgeWVhciBlZmZlY3QgaXRzZWxmLiAgSW4gdGhlIGJvdHRvbSBwbG90LAojJyB0aGUgY2lyY2xlcyBtYXJrIDEzdGggZGF5IG9mIGVhY2ggbW9udGguIFJlc3VsdHMgbG9vayBzaW1pbGFyIHRvCiMnIG91ciBwcmV2aW91cyBhbmFseXNlcyAsIHNvIGl0IHNlZW1zIHRoZSBkYXkgb3IgeWVhciBlZmZlY3QgbW9kZWwKIycgY29tcG9uZW50IGlzIHdvcmtpbmcgYXMgaXQgc2hvdWxkLCBidXQgdGhlcmUgd2FzIHNvbWUgcHJvYmxlbSB3aXRoCiMnIG91ciBSSFMgaW1wbGVtZW50YXRpb24uIEFzIHRoZXJlIGlzIG1vcmUgdmFyaWF0aW9uIGluIHRoZSBkYXkgb2YKIycgeWVhciBlZmZlY3RzIHRoYW4gd2Ugd291bGQgaG9wZSwgd2UgZGlkIHNvbWUgYWRkaXRpb25hbCBleHBlcmltZW50cwojJyB3aXRoIGRpZmZlcmVudCBwcmlvcnMgZm9yIHRoZSBkYXkgb2YgeWVhciBlZmZlY3QgKGRvdWJsZQojJyBleHBvbmVudGlhbCwgQ2F1Y2h5IGFuZCBTdHVkZW50J3MgdCB3aXRoIHVua25vd24gZGVncmVlcyBvZiBmcmVlZG9tCiMnIGFzIG1vZGVscyA2YiwgNmMsIDZkKSwgYnV0IGRlY2lkZWQgaXQncyBiZXR0ZXIgdG8gYWRkIG90aGVyCiMnIGNvbXBvbmVudHMgYmVmb3JlIGludmVzdGluZyB0aGF0IHBhcnQgbW9yZSB0aG9yb3VnaGx5LgojJyAKCiMnICMjIyBNb2RlbCA3OiBsb25nIHRlcm0gc21vb3RoICsgc2Vhc29uYWwgKyB3ZWVrZGF5ICsgZGF5IG9mIHllYXIgbm9ybWFsICsgZmxvYXRpbmcgc3BlY2lhbCBkYXlzCiMnCiMnIFdlIGNhbiBzZWUgaW4gdGhlIG1vZGVsIDYgcmVzdWx0cyB0aGF0IGRheSBvZiB5ZWFyIGVmZmVjdHMgaGF2ZQojJyBzb21lIGRpcHMgaW4gdGhlIHJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgdGhhdCBhcmUgc3ByZWFkIG92ZXIgYQojJyB3ZWVrLiBGcm9tIHByZXZpb3VzIGFuYWx5c2Ugd2Uga25vdyB0aGVzZSBjb3JyZXNwb25kIHRvIGhvbGlkYXlzCiMnIHRoYXQgYXJlIG5vdCBvbiBhIHNwZWNpZmljIGRheSBvZiB5ZWFyLCBidXQgYXJlIGZvciBleGFtcGxlIG9uIHRoZQojJyBsYXN0IE1vbmRheSBvZiBNYXkuIFdlIGNhbGwgdGhlc2UgZmxvYXRpbmcgc3BlY2lhbCBkYXlzIGFuZCBpbmNsdWRlCiMnIE1lbW9yaWFsIGRheSAobGFzdCBNb25kYXkgb2YgTWF5KSwgTGFib3IgZGF5IChmaXJzdCBNb25kYXkgb2YKIycgU2VwdGVtYmVyLCBhbmQgd2UgaW5jbHVkZSBhbHNvIHRoZSBmb2xsb3dpbmcgVHVlc2RheSksIGFuZAojJyBUaGFua3NnaXZpbmcgKGZvdXJ0aCBUaHVyc2RheSBvZiBOb3ZlbWJlciwgYW5kIHdlIGluY2x1ZGUgYWxzbyB0aGUKIycgZm9sbG93aW5nIEZyaWRheSkuCiMnCiMnIENvbXBpbGUgU3RhbiBtb2RlbCA3IFtncGJmNy5zdGFuXShodHRwczovL2dpdGh1Yi5jb20vYXZlaHRhcmkvY2FzZXN0dWRpZXMvYmxvYi9tYXN0ZXIvQmlydGhkYXlzL2dwYmY3LnN0YW4pCiMrIG1vZGVsNywgcmVzdWx0cz0naGlkZScKbW9kZWw3IDwtIGNtZHN0YW5fbW9kZWwoc3Rhbl9maWxlID0gcm9vdCgiQmlydGhkYXlzIiwgImdwYmY3LnN0YW4iKSwKICAgICAgICAgICAgICAgICAgICAgICAgaW5jbHVkZV9wYXRocyA9IHJvb3QoIkJpcnRoZGF5cyIpKQoKIycgRmxvYXRpbmcgc3BlY2lhbCBkYXlzCiMgTWVtb3JpYWwgZGF5Cm1lbW9yaWFsX2RheXMgPC0gd2l0aChkYXRhLHdoaWNoKG1vbnRoPT01JmRheV9vZl93ZWVrPT0xJmRheT49MjUpKQojIExhYm9yIGRheQpsYWJvcl9kYXlzIDwtIHdpdGgoZGF0YSx3aGljaChtb250aD09OSZkYXlfb2Zfd2Vlaz09MSZkYXk8PTcpKQpsYWJvcl9kYXlzIDwtIGMobGFib3JfZGF5cywgbGFib3JfZGF5cysxKQojIFRoYW5rc2dpdmluZwp0aGFua3NnaXZpbmdfZGF5cyA8LSB3aXRoKGRhdGEsd2hpY2gobW9udGg9PTExJmRheV9vZl93ZWVrPT00JmRheT49MjImZGF5PD0yOCkpCnRoYW5rc2dpdmluZ19kYXlzIDwtIGModGhhbmtzZ2l2aW5nX2RheXMsIHRoYW5rc2dpdmluZ19kYXlzKzEpCgojJyBEYXRhIHRvIGJlIHBhc3NlZCB0byBTdGFuCnN0YW5kYXRhNyA8LSBsaXN0KHg9ZGF0YSRpZCwKICAgICAgICAgICAgICAgICAgeT1sb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApLAogICAgICAgICAgICAgICAgICBOPWxlbmd0aChkYXRhJGlkKSwKICAgICAgICAgICAgICAgICAgY19mMT0xLjUsICMgZmFjdG9yIGMgb2YgYmFzaXMgZnVuY3Rpb25zIGZvciBHUCBmb3IgZjEKICAgICAgICAgICAgICAgICAgTV9mMT0xMCwgICMgbnVtYmVyIG9mIGJhc2lzIGZ1bmN0aW9ucyBmb3IgR1AgZm9yIGYxCiAgICAgICAgICAgICAgICAgIEpfZjI9MjAsICAjIG51bWJlciBvZiBiYXNpcyBmdW5jdGlvbnMgZm9yIHBlcmlvZGljIGYyCiAgICAgICAgICAgICAgICAgIGRheV9vZl93ZWVrPWRhdGEkZGF5X29mX3dlZWssCiAgICAgICAgICAgICAgICAgIGRheV9vZl95ZWFyPWRhdGEkZGF5X29mX3llYXIyLCAjIDFzdCBNYXJjaCA9IDYxIGV2ZXJ5IHllYXIKICAgICAgICAgICAgICAgICAgbWVtb3JpYWxfZGF5cz1tZW1vcmlhbF9kYXlzLAogICAgICAgICAgICAgICAgICBsYWJvcl9kYXlzPWxhYm9yX2RheXMsCiAgICAgICAgICAgICAgICAgIHRoYW5rc2dpdmluZ19kYXlzPXRoYW5rc2dpdmluZ19kYXlzKQoKIycgT3B0aW1pemluZyBpcyBmYXN0ZXIgdGhhbiBzYW1wbGluZyAoYWx0aG91Z2ggdGhpcyByZXN1bHQgY2FuIGJlCiMnIHVzZWZ1bCBpbiBhIHF1aWNrIHdvcmtmbG93LCB0aGUgcmVzdWx0IHNob3VsZCBub3QgYmUgdXNlZCBhcyB0aGUKIycgZmluYWwgcmVzdWx0KS4KIysgb3B0NywgcmVzdWx0cz0naGlkZScKb3B0NyA8LSBtb2RlbDckb3B0aW1pemUoZGF0YT1zdGFuZGF0YTcsIGluaXQ9MCwgYWxnb3JpdGhtPSdsYmZncycsCiAgICAgICAgICAgICAgICAgICAgICAgIGhpc3Rvcnk9MTAwLCB0b2xfb2JqPTEwKQoKIycgQ2hlY2sgd2hldGhlciBwYXJhbWV0ZXJzIGhhdmUgcmVhc29uYWJsZSB2YWx1ZXMKb2RyYXdzNyA8LSBvcHQ3JGRyYXdzKCkKc3Vic2V0KG9kcmF3czcsIHZhcmlhYmxlPWMoJ2ludGVyY2VwdCcsJ3NpZ21hXycsJ2xlbmd0aHNjYWxlXycsJ3NpZ21hJyksIHJlZ2V4PVRSVUUpCnN1YnNldChvZHJhd3M3LCB2YXJpYWJsZT1jKCdiZXRhX2YzJykpCkVmNCA8LSBhcy5udW1lcmljKHN1YnNldChvZHJhd3M3LCB2YXJpYWJsZT0nYmV0YV9mNCcpKSpzZChsb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApKQpFZjQgPC0gZXhwKEVmNCkqMTAwCmRhdGEuZnJhbWUoeD1hcy5EYXRlKCIxOTg4LTAxLTAxIikrMDozNjUsIHk9RWY0KSAlPiUKICBnZ3Bsb3QoYWVzKHg9eCx5PXkpKSArIGdlb21fbGluZShjb2xvcj1zZXQxWzFdKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCBkYXRlX2xhYmVscyA9ICIlYiIpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIG9mIHllYXIiKQoKIycgU2FtcGxlIHNob3J0IGNoYWlucyB1c2luZyB0aGUgZWFybHkgc3RvcHBlZCBvcHRpbWl6YXRpb24gcmVzdWx0IGFzCiMnIGluaXRpYWwgdmFsdWVzIChhbHRob3VnaCB0aGUgcmVzdWx0IGZyb20gc2hvcnQgY2hhaW5zIGNhbiBiZSB1c2VmdWwKIycgaW4gYSBxdWljayB3b3JrZmxvdywgdGhlIHJlc3VsdCBzaG91bGQgbm90IGJlIHVzZWQgYXMgdGhlIGZpbmFsCiMnIHJlc3VsdCkuCmluaXQ3IDwtIHNhcHBseShjKCdpbnRlcmNlcHQwJywnbGVuZ3Roc2NhbGVfZjEnLCdsZW5ndGhzY2FsZV9mMicsCiAgICAgICAgICAgICAgICAgICdzaWdtYV9mMScsJ3NpZ21hX2YyJywnc2lnbWFfZjQnLCdzaWdtYScsCiAgICAgICAgICAgICAgICAgICdiZXRhX2YxJywnYmV0YV9mMicsJ2JldGFfZjMnLCdiZXRhX2Y0JywnYmV0YV9mNScpLAogICAgICAgICAgICAgICAgZnVuY3Rpb24odmFyaWFibGUpIHthcy5udW1lcmljKHN1YnNldChvZHJhd3M3LCB2YXJpYWJsZT12YXJpYWJsZSkpfSkKIysgZml0NywgcmVzdWx0cz0naGlkZScKZml0NyA8LSBtb2RlbDckc2FtcGxlKGRhdGE9c3RhbmRhdGE3LCBpdGVyX3dhcm11cD0xMDAsIGl0ZXJfc2FtcGxpbmc9MTAwLCBjaGFpbnM9NCwgcGFyYWxsZWxfY2hhaW5zPTQsCiAgICAgICAgICAgICAgICAgICAgICBpbml0PWZ1bmN0aW9uKCkgeyBpbml0NyB9LCByZWZyZXNoPTEwKQoKIycgQ2hlY2sgd2hldGhlciBwYXJhbWV0ZXJzIGhhdmUgcmVhc29uYWJsZSB2YWx1ZXMKZHJhd3M3IDwtIGZpdDckZHJhd3MoKQpzdW1tYXJpc2VfZHJhd3Moc3Vic2V0KGRyYXdzNywgdmFyaWFibGU9YygnaW50ZXJjZXB0Jywnc2lnbWFfJywnbGVuZ3Roc2NhbGVfJywnc2lnbWEnKSwgcmVnZXg9VFJVRSkpCnN1bW1hcmlzZV9kcmF3cyhzdWJzZXQoZHJhd3M3LCB2YXJpYWJsZT1jKCdiZXRhX2YzJykpKQoKIycgQ29tcGFyZSB0aGUgbW9kZWwgdG8gdGhlIGRhdGEKZHJhd3M3IDwtIGFzX2RyYXdzX21hdHJpeChkcmF3czcpCkVmIDwtIGV4cChhcHBseShzdWJzZXQoZHJhd3M3LCB2YXJpYWJsZT0nZicpLCAyLCBtZWRpYW4pKQpFZjEgPC0gYXBwbHkoc3Vic2V0KGRyYXdzNywgdmFyaWFibGU9J2YxJyksIDIsIG1lZGlhbikKRWYxIDwtIGV4cChFZjEgLSBtZWFuKEVmMSkgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZjIgPC0gYXBwbHkoc3Vic2V0KGRyYXdzNywgdmFyaWFibGU9J2YyJyksIDIsIG1lZGlhbikKRWYyIDwtIGV4cChFZjIgLSBtZWFuKEVmMikgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZl9kYXlfb2Zfd2VlayA8LSBhcHBseShzdWJzZXQoZHJhd3M3LCB2YXJpYWJsZT0nZl9kYXlfb2Zfd2VlaycpLCAyLCBtZWRpYW4pCkVmX2RheV9vZl93ZWVrIDwtIGV4cChFZl9kYXlfb2Zfd2VlayAtIG1lYW4oRWZfZGF5X29mX3dlZWspICsgbWVhbihsb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApKSkKRWY0IDwtIGFwcGx5KHN1YnNldChkcmF3czcsIHZhcmlhYmxlPSdiZXRhX2Y0JyksIDIsIG1lZGlhbikqc2QobG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkKRWY0IDwtIGV4cChFZjQpKjEwMApFZmxvYXRzIDwtIGFwcGx5KHN1YnNldChkcmF3czcsIHZhcmlhYmxlPSdiZXRhX2Y1JyksIDIsIG1lZGlhbikqc2QobG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkKRWZsb2F0cyA8LSBleHAoRWZsb2F0cykqMTAwCmZsb2F0czE5ODg8LWMobWVtb3JpYWxfZGF5c1syMF0sIGxhYm9yX2RheXNbYygyMCw0MCldLCB0aGFua3NnaXZpbmdfZGF5c1tjKDIwLDQwKV0pLTY5MzkKRWY0ZmxvYXQgPC0gRWY0CkVmNGZsb2F0W2Zsb2F0czE5ODhdIDwtIEVmNGZsb2F0W2Zsb2F0czE5ODhdKkVmbG9hdHNbYygxLDIsMiwzLDMpXS8xMDAKcGYgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYgPSBFZikgJT4lCiAgZ2dwbG90KGFlcyh4PWRhdGUsIHk9YmlydGhzX3JlbGF0aXZlMTAwKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIGdlb21fbGluZShhZXMoeT1FZiksIGNvbG9yPXNldDFbMV0sIGFscGhhPTAuNzUpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIikKcGYxIDwtIGRhdGEgJT4lCiAgbXV0YXRlKEVmMSA9IEVmMSkgJT4lCiAgZ2dwbG90KGFlcyh4PWRhdGUsIHk9YmlydGhzX3JlbGF0aXZlMTAwKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIGdlb21fbGluZShhZXMoeT1FZjEpLCBjb2xvcj1zZXQxWzFdKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyIpCnBmMiA8LSBkYXRhICU+JQogIG11dGF0ZShFZjIgPSBFZjIpICU+JQogIGdyb3VwX2J5KGRheV9vZl95ZWFyMikgJT4lCiAgc3VtbWFyaXNlKG1lYW5iaXJ0aHM9bWVhbihiaXJ0aHNfcmVsYXRpdmUxMDApLCBtZWFuRWYyPW1lYW4oRWYyKSkgJT4lCiAgZ2dwbG90KGFlcyh4PWFzLkRhdGUoIjE5ODctMTItMzEiKStkYXlfb2ZfeWVhcjIsIHk9bWVhbmJpcnRocykpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikgKwogIGdlb21fbGluZShhZXMoeT1tZWFuRWYyKSwgY29sb3I9c2V0MVsxXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgb2YgeWVhciIpCnBmMyA8LSBnZ3Bsb3QoZGF0YT1kYXRhLCBhZXMoeD1kYXlfb2Zfd2VlaywgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IDE6NywgbGFiZWxzPWMoJ01vbicsJ1R1ZScsJ1dlZCcsJ1RodScsJ0ZyaScsJ1NhdCcsJ1N1bicpKSArCiAgZ2VvbV9saW5lKGRhdGE9ZGF0YS5mcmFtZSh4PTE6Nyx5PUVmX2RheV9vZl93ZWVrKSwgYWVzKHg9eCwgeT1FZl9kYXlfb2Zfd2VlayksIGNvbG9yPXNldDFbMV0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIG9mIHdlZWsiKQpmMTMgPC0gZGF0YSAlPiUgZmlsdGVyKHllYXI9PTE5ODgpJT4lc2VsZWN0KGRheSxkYXRlKSU+JW11dGF0ZSh5PUVmNGZsb2F0KSU+JWZpbHRlcihkYXk9PTEzKQoKcGYyYiA8LWRhdGEuZnJhbWUoeD1hcy5EYXRlKCIxOTg4LTAxLTAxIikrMDozNjUsIHk9RWY0ZmxvYXQpICU+JQogIGdncGxvdChhZXMoeD14LHk9eSkpICsgZ2VvbV9saW5lKGNvbG9yPXNldDFbMV0pICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgb2YgeWVhciIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTAxLTAxIikseT1FZjRmbG9hdFsxXS0xLGxhYmVsPSJOZXcgeWVhciIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTAyLTE0IikseT1FZjRmbG9hdFs0NV0rMS41LGxhYmVsPSJWYWxlbnRpbmUncyBkYXkiKSArCiAgYW5ub3RhdGUoInRleHQiLHg9YXMuRGF0ZSgiMTk4OC0wMi0yOSIpLHk9RWY0ZmxvYXRbNjBdLTIuNSxsYWJlbD0iTGVhcCBkYXkiKSArCiAgYW5ub3RhdGUoInRleHQiLHg9YXMuRGF0ZSgiMTk4OC0wNC0wMSIpLHk9RWY0ZmxvYXRbOTJdLTEuNSxsYWJlbD0iQXByaWwgMXN0IikgKyAKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTA3LTA0IikseT1FZjRmbG9hdFsxODZdLTEuNSxsYWJlbD0iSW5kZXBlbmRlbmNlIGRheSIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTEwLTMxIikseT1FZjRmbG9hdFszMDVdLTEuNSxsYWJlbD0iSGFsbG93ZWVuIikgKyAKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTEyLTI0IikseT1FZjRmbG9hdFszNjBdLTIsbGFiZWw9IkNocmlzdG1hcyIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTA1LTMwIikseT1FZjRmbG9hdFsxNTFdLTEuNSxsYWJlbD0iTWVtb3JpYWwgZGF5IikgKwogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMDktMDUiKSx5PUVmNGZsb2F0WzI0OV0tMS41LGxhYmVsPSJMYWJvciBkYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMTEtMjQiKSx5PUVmNGZsb2F0WzMyOV0tMSxsYWJlbD0iVGhhbmtzZ2l2aW5nIikrCiAgZ2VvbV9wb2ludChkYXRhPWYxMyxhZXMoeD1kYXRlLHk9eSksIHNpemU9Mywgc2hhcGU9MSkKKHBmICsgcGYxKSAvIChwZjIgKyBwZjMpIC8gKHBmMmIpCgojJyBUaGUgZGF5IG9mIHllYXIgYW5kIGZsb2F0aW5nIHNwZWNpYWwgZGF5IGVmZmVjdHMgYXJlIHNob3duIGZvciB5ZWFyCiMnIDE5ODggKHdoaWNoIGlzIGFsc28gYSBsZWFwIHllYXIpIGFuZCB0aGUgcmVzdWx0cyBzZWVtIHJlYXNvbmFibGUuCiMnIAoKIycgIyMjIE1vZGVsIDg6IGxvbmcgdGVybSBzbW9vdGggKyBzZWFzb25hbCArIHdlZWtkYXkgd2l0aCB0aW1lIGRlcGVuZGVudCBtYWduaXR1ZGUgKyBkYXkgb2YgeWVhciArIHNwZWNpYWwKIycKIycgQXMgdGhlIGRheSBvZiB5ZWFyIGFuZCBmbG9hdGluZyBkYXkgZWZmZWN0cyB3b3JrIHdlbGwsIHdlJ2xsIGFkZAojJyB0aGUgdGltZSBkZXBlbmRlbnQgZGF5IG9mIHdlZWsgZWZmZWN0IGJhY2sgdG8gdGhlIG1vZGVsLgojJyAKIycgQ29tcGlsZSBTdGFuIG1vZGVsIDggW2dwYmY4LnN0YW5dKGh0dHBzOi8vZ2l0aHViLmNvbS9hdmVodGFyaS9jYXNlc3R1ZGllcy9ibG9iL21hc3Rlci9CaXJ0aGRheXMvZ3BiZjguc3RhbikKIysgbW9kZWw4LCByZXN1bHRzPSdoaWRlJwptb2RlbDggPC0gY21kc3Rhbl9tb2RlbChzdGFuX2ZpbGUgPSByb290KCJCaXJ0aGRheXMiLCAiZ3BiZjguc3RhbiIpLAogICAgICAgICAgICAgICAgICAgICAgICBpbmNsdWRlX3BhdGhzID0gcm9vdCgiQmlydGhkYXlzIikpCgojJyBGbG9hdGluZyBzcGVjaWFsIGRheXMKIyBNZW1vcmlhbCBkYXkKbWVtb3JpYWxfZGF5cyA8LSB3aXRoKGRhdGEsd2hpY2gobW9udGg9PTUmZGF5X29mX3dlZWs9PTEmZGF5Pj0yNSkpCiMgTGFib3IgZGF5CmxhYm9yX2RheXMgPC0gd2l0aChkYXRhLHdoaWNoKG1vbnRoPT05JmRheV9vZl93ZWVrPT0xJmRheTw9NykpCmxhYm9yX2RheXMgPC0gYyhsYWJvcl9kYXlzLCBsYWJvcl9kYXlzKzEpCiMgVGhhbmtzZ2l2aW5nCnRoYW5rc2dpdmluZ19kYXlzIDwtIHdpdGgoZGF0YSx3aGljaChtb250aD09MTEmZGF5X29mX3dlZWs9PTQmZGF5Pj0yMiZkYXk8PTI4KSkKdGhhbmtzZ2l2aW5nX2RheXMgPC0gYyh0aGFua3NnaXZpbmdfZGF5cywgdGhhbmtzZ2l2aW5nX2RheXMrMSkKCiMnIERhdGEgdG8gYmUgcGFzc2VkIHRvIFN0YW4Kc3RhbmRhdGE4IDwtIGxpc3QoeD1kYXRhJGlkLAogICAgICAgICAgICAgICAgICB5PWxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCksCiAgICAgICAgICAgICAgICAgIE49bGVuZ3RoKGRhdGEkaWQpLAogICAgICAgICAgICAgICAgICBjX2YxPTEuNSwgIyBmYWN0b3IgYyBvZiBiYXNpcyBmdW5jdGlvbnMgZm9yIEdQIGZvciBmMQogICAgICAgICAgICAgICAgICBNX2YxPTEwLCAgIyBudW1iZXIgb2YgYmFzaXMgZnVuY3Rpb25zIGZvciBHUCBmb3IgZjEKICAgICAgICAgICAgICAgICAgSl9mMj0yMCwgICMgbnVtYmVyIG9mIGJhc2lzIGZ1bmN0aW9ucyBmb3IgcGVyaW9kaWMgZjIKICAgICAgICAgICAgICAgICAgY19nMz0xLjUsICMgZmFjdG9yIGMgb2YgYmFzaXMgZnVuY3Rpb25zIGZvciBHUCBmb3IgZzMKICAgICAgICAgICAgICAgICAgTV9nMz01LCAgICMgbnVtYmVyIG9mIGJhc2lzIGZ1bmN0aW9ucyBmb3IgR1AgZm9yIGczCiAgICAgICAgICAgICAgICAgIGRheV9vZl93ZWVrPWRhdGEkZGF5X29mX3dlZWssCiAgICAgICAgICAgICAgICAgIGRheV9vZl95ZWFyPWRhdGEkZGF5X29mX3llYXIyLCAjIDFzdCBNYXJjaCA9IDYxIGV2ZXJ5IHllYXIKICAgICAgICAgICAgICAgICAgbWVtb3JpYWxfZGF5cz1tZW1vcmlhbF9kYXlzLAogICAgICAgICAgICAgICAgICBsYWJvcl9kYXlzPWxhYm9yX2RheXMsCiAgICAgICAgICAgICAgICAgIHRoYW5rc2dpdmluZ19kYXlzPXRoYW5rc2dpdmluZ19kYXlzKQoKIycgT3B0aW1pemluZyBpcyBmYXN0ZXIgdGhhbiBzYW1wbGluZyAoYWx0aG91Z2ggdGhpcyByZXN1bHQgY2FuIGJlCiMnIHVzZWZ1bCBpbiBhIHF1aWNrIHdvcmtmbG93LCB0aGUgcmVzdWx0IHNob3VsZCBub3QgYmUgdXNlZCBhcyB0aGUKIycgZmluYWwgcmVzdWx0KS4KIysgb3B0OCwgcmVzdWx0cz0naGlkZScKb3B0OCA8LSBtb2RlbDgkb3B0aW1pemUoZGF0YT1zdGFuZGF0YTgsIGluaXQ9MC4xLCBhbGdvcml0aG09J2xiZmdzJywKICAgICAgICAgICAgICAgICAgICAgICAgaGlzdG9yeT0xMDAsIHRvbF9vYmo9MTApCgojJyBDaGVjayB3aGV0aGVyIHBhcmFtZXRlcnMgaGF2ZSByZWFzb25hYmxlIHZhbHVlcwpvZHJhd3M4IDwtIG9wdDgkZHJhd3MoKQpzdWJzZXQob2RyYXdzOCwgdmFyaWFibGU9YygnaW50ZXJjZXB0Jywnc2lnbWFfJywnbGVuZ3Roc2NhbGVfJywnc2lnbWEnKSwgcmVnZXg9VFJVRSkKc3Vic2V0KG9kcmF3czgsIHZhcmlhYmxlPWMoJ2JldGFfZjMnKSkKRWY0IDwtIGFzLm51bWVyaWMoc3Vic2V0KG9kcmF3czgsIHZhcmlhYmxlPSdiZXRhX2Y0JykpKnNkKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpCkVmNCA8LSBleHAoRWY0KSoxMDAKZGF0YS5mcmFtZSh4PWFzLkRhdGUoIjE5ODgtMDEtMDEiKSswOjM2NSwgeT1FZjQpICU+JQogIGdncGxvdChhZXMoeD14LHk9eSkpICsgZ2VvbV9saW5lKGNvbG9yPXNldDFbMV0pICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgb2YgeWVhciIpCgojJyBDb21wYXJlIHRoZSBtb2RlbCB0byB0aGUgZGF0YQpFZiA8LSBleHAoYXMubnVtZXJpYyhzdWJzZXQob2RyYXdzOCwgdmFyaWFibGU9J2YnKSkpCkVmMSA8LSBhcy5udW1lcmljKHN1YnNldChvZHJhd3M4LCB2YXJpYWJsZT0nZjEnKSkKRWYxIDwtIGV4cChFZjEgLSBtZWFuKEVmMSkgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZjIgPC0gYXMubnVtZXJpYyhzdWJzZXQob2RyYXdzOCwgdmFyaWFibGU9J2YyJykpCkVmMiA8LSBleHAoRWYyIC0gbWVhbihFZjIpICsgbWVhbihsb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApKSkKRWZfZGF5X29mX3dlZWsgPC0gYXMubnVtZXJpYyhzdWJzZXQob2RyYXdzOCwgdmFyaWFibGU9J2ZfZGF5X29mX3dlZWsnKSkKRWZfZGF5X29mX3dlZWsgPC0gZXhwKEVmX2RheV9vZl93ZWVrIC0gbWVhbihFZl9kYXlfb2Zfd2VlaykgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZjMgPC0gYXMubnVtZXJpYyhzdWJzZXQob2RyYXdzOCwgdmFyaWFibGU9J2YzJykpCkVmMyA8LSBleHAoRWYzIC0gbWVhbihFZjMpICsgbWVhbihsb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApKSkKRWY0IDwtIGFzLm51bWVyaWMoc3Vic2V0KG9kcmF3czgsIHZhcmlhYmxlPSdiZXRhX2Y0JykpKnNkKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpCkVmNCA8LSBleHAoRWY0KSoxMDAKRWZsb2F0cyA8LSBhcy5udW1lcmljKHN1YnNldChvZHJhd3M4LCB2YXJpYWJsZT0nYmV0YV9mNScpKSpzZChsb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApKQpFZmxvYXRzIDwtIGV4cChFZmxvYXRzKSoxMDAKZmxvYXRzMTk4ODwtYyhtZW1vcmlhbF9kYXlzWzIwXSwgbGFib3JfZGF5c1tjKDIwLDQwKV0sIHRoYW5rc2dpdmluZ19kYXlzW2MoMjAsNDApXSktNjkzOQpFZjRmbG9hdCA8LSBFZjQKRWY0ZmxvYXRbZmxvYXRzMTk4OF0gPC0gRWY0ZmxvYXRbZmxvYXRzMTk4OF0qRWZsb2F0c1tjKDEsMiwyLDMsMyldLzEwMApwZiA8LSBkYXRhICU+JQogIG11dGF0ZShFZiA9IEVmKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9wb2ludChhZXMoeT1FZiksIGNvbG9yPXNldDFbMV0sIGFscGhhPTAuMikgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMiKQpwZjEgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYxID0gRWYxKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9saW5lKGFlcyh5PUVmMSksIGNvbG9yPXNldDFbMV0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIikKcGYyIDwtIGRhdGEgJT4lCiAgbXV0YXRlKEVmMiA9IEVmMikgJT4lCiAgZ3JvdXBfYnkoZGF5X29mX3llYXIyKSAlPiUKICBzdW1tYXJpc2UobWVhbmJpcnRocz1tZWFuKGJpcnRoc19yZWxhdGl2ZTEwMCksIG1lYW5FZjI9bWVhbihFZjIpKSAlPiUKICBnZ3Bsb3QoYWVzKHg9YXMuRGF0ZSgiMTk4Ny0xMi0zMSIpK2RheV9vZl95ZWFyMiwgeT1tZWFuYmlydGhzKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKSArCiAgZ2VvbV9saW5lKGFlcyh5PW1lYW5FZjIpLCBjb2xvcj1zZXQxWzFdKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyBvZiB5ZWFyIikKcGYzIDwtIGdncGxvdChkYXRhPWRhdGEsIGFlcyh4PWRheV9vZl93ZWVrLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gMTo3LCBsYWJlbHM9YygnTW9uJywnVHVlJywnV2VkJywnVGh1JywnRnJpJywnU2F0JywnU3VuJykpICsKICBnZW9tX2xpbmUoZGF0YT1kYXRhLmZyYW1lKHg9MTo3LHk9RWZfZGF5X29mX3dlZWspLCBhZXMoeD14LCB5PUVmX2RheV9vZl93ZWVrKSwgY29sb3I9c2V0MVsxXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgb2Ygd2VlayIpCk49bGVuZ3RoKGRhdGEkaWQpCnBmM2IgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYzID0gRWYzKkVmMS8xMDApICU+JQogIGdncGxvdChhZXMoeD1kYXRlLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBnZW9tX3BvaW50KGFlcyh5PUVmMyksIGNvbG9yPXNldDFbMV0sIHNpemU9MC4xKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg5LTA4LTAxIikseT0oRWYzKkVmMS8xMDApW2MoKE4tNSk6KE4tNCksIE4sIE4tNildLGxhYmVsPWMoIk1vbiIsIlR1ZSIsIlNhdCIsIlN1biIpKQpmMTMgPC0gZGF0YSAlPiUgZmlsdGVyKHllYXI9PTE5ODgpJT4lc2VsZWN0KGRheSxkYXRlKSU+JW11dGF0ZSh5PUVmNGZsb2F0KSU+JWZpbHRlcihkYXk9PTEzKQpwZjJiIDwtZGF0YS5mcmFtZSh4PWFzLkRhdGUoIjE5ODgtMDEtMDEiKSswOjM2NSwgeT1FZjRmbG9hdCkgJT4lCiAgZ2dwbG90KGFlcyh4PXgseT15KSkgKyBnZW9tX2xpbmUoY29sb3I9c2V0MVsxXSkgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyBvZiB5ZWFyIikgKwogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMDEtMDEiKSx5PUVmNGZsb2F0WzFdLTEsbGFiZWw9Ik5ldyB5ZWFyIikgKwogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMDItMTQiKSx5PUVmNGZsb2F0WzQ1XSsxLjUsbGFiZWw9IlZhbGVudGluZSdzIGRheSIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTAyLTI5IikseT1FZjRmbG9hdFs2MF0tMi41LGxhYmVsPSJMZWFwIGRheSIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTA0LTAxIikseT1FZjRmbG9hdFs5Ml0tMS41LGxhYmVsPSJBcHJpbCAxc3QiKSArIAogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMDctMDQiKSx5PUVmNGZsb2F0WzE4Nl0tMS41LGxhYmVsPSJJbmRlcGVuZGVuY2UgZGF5IikgKwogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMTAtMzEiKSx5PUVmNGZsb2F0WzMwNV0tMS41LGxhYmVsPSJIYWxsb3dlZW4iKSArIAogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMTItMjQiKSx5PUVmNGZsb2F0WzM2MF0tMixsYWJlbD0iQ2hyaXN0bWFzIikgKwogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMDUtMzAiKSx5PUVmNGZsb2F0WzE1MV0tMixsYWJlbD0iTWVtb3JpYWwgZGF5IikgKwogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMDktMDUiKSx5PUVmNGZsb2F0WzI0OV0tMS41LGxhYmVsPSJMYWJvciBkYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMTEtMjQiKSx5PUVmNGZsb2F0WzMyOV0tMSxsYWJlbD0iVGhhbmtzZ2l2aW5nIikrCiAgZ2VvbV9wb2ludChkYXRhPWYxMyxhZXMoeD1kYXRlLHk9eSksIHNpemU9Mywgc2hhcGU9MSkKKHBmICsgcGYxKSAvIChwZjIgKyBwZjNiKSAvIChwZjJiKQoKIycgU2FtcGxlIHNob3J0IGNoYWlucyB1c2luZyB0aGUgZWFybHkgc3RvcHBlZCBvcHRpbWl6YXRpb24gcmVzdWx0IGFzCiMnIGluaXRpYWwgdmFsdWVzIChhbHRob3VnaCB0aGUgcmVzdWx0IGZyb20gc2hvcnQgY2hhaW5zIGNhbiBiZSB1c2VmdWwKIycgaW4gYSBxdWljayB3b3JrZmxvdywgdGhlIHJlc3VsdCBzaG91bGQgbm90IGJlIHVzZWQgYXMgdGhlIGZpbmFsCiMnIHJlc3VsdCkuCmluaXQ4IDwtIHNhcHBseShjKCdpbnRlcmNlcHQwJywnbGVuZ3Roc2NhbGVfZjEnLCdsZW5ndGhzY2FsZV9mMicsJ2xlbmd0aHNjYWxlX2czJywKICAgICAgICAgICAgICAgICAgJ3NpZ21hX2YxJywnc2lnbWFfZjInLCdzaWdtYV9nMycsJ3NpZ21hX2Y0Jywnc2lnbWEnLAogICAgICAgICAgICAgICAgICAnYmV0YV9mMScsJ2JldGFfZjInLCdiZXRhX2YzJywnYmV0YV9nMycsJ2JldGFfZjQnLCdiZXRhX2Y1JyksCiAgICAgICAgICAgICAgICBmdW5jdGlvbih2YXJpYWJsZSkge2FzLm51bWVyaWMoc3Vic2V0KG9kcmF3czgsIHZhcmlhYmxlPXZhcmlhYmxlKSl9KQojKyBmaXQ4LCByZXN1bHRzPSdoaWRlJwpmaXQ4IDwtIG1vZGVsOCRzYW1wbGUoZGF0YT1zdGFuZGF0YTgsIGl0ZXJfd2FybXVwPTEwMCwgaXRlcl9zYW1wbGluZz0xMDAsIGNoYWlucz00LCBwYXJhbGxlbF9jaGFpbnM9NCwKICAgICAgICAgICAgICAgICAgICAgIGluaXQ9ZnVuY3Rpb24oKSB7IGluaXQ4IH0sIHJlZnJlc2g9MTApCgojJyBDaGVjayB3aGV0aGVyIHBhcmFtZXRlcnMgaGF2ZSByZWFzb25hYmxlIHZhbHVlcwpkcmF3czggPC0gZml0OCRkcmF3cygpCnN1bW1hcmlzZV9kcmF3cyhzdWJzZXQoZHJhd3M4LCB2YXJpYWJsZT1jKCdpbnRlcmNlcHQnLCdzaWdtYV8nLCdsZW5ndGhzY2FsZV8nLCdzaWdtYScpLCByZWdleD1UUlVFKSkKc3VtbWFyaXNlX2RyYXdzKHN1YnNldChkcmF3czgsIHZhcmlhYmxlPWMoJ2JldGFfZjMnKSkpCgojJyBDb21wYXJlIHRoZSBtb2RlbCB0byB0aGUgZGF0YQpkcmF3czggPC0gYXNfZHJhd3NfbWF0cml4KGRyYXdzOCkKRWYgPC0gZXhwKGFwcGx5KHN1YnNldChkcmF3czgsIHZhcmlhYmxlPSdmJyksIDIsIG1lZGlhbikpCkVmMSA8LSBhcHBseShzdWJzZXQoZHJhd3M4LCB2YXJpYWJsZT0nZjEnKSwgMiwgbWVkaWFuKQpFZjEgPC0gZXhwKEVmMSAtIG1lYW4oRWYxKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCkVmMiA8LSBhcHBseShzdWJzZXQoZHJhd3M4LCB2YXJpYWJsZT0nZjInKSwgMiwgbWVkaWFuKQpFZjIgPC0gZXhwKEVmMiAtIG1lYW4oRWYyKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCkVmX2RheV9vZl93ZWVrIDwtIGFwcGx5KHN1YnNldChkcmF3czgsIHZhcmlhYmxlPSdmX2RheV9vZl93ZWVrJyksIDIsIG1lZGlhbikKRWZfZGF5X29mX3dlZWsgPC0gZXhwKEVmX2RheV9vZl93ZWVrIC0gbWVhbihFZl9kYXlfb2Zfd2VlaykgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZjMgPC0gYXBwbHkoc3Vic2V0KGRyYXdzOCwgdmFyaWFibGU9J2YzJyksIDIsIG1lZGlhbikKRWYzIDwtIGV4cChFZjMgLSBtZWFuKEVmMykgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZjQgPC0gYXBwbHkoc3Vic2V0KGRyYXdzOCwgdmFyaWFibGU9J2JldGFfZjQnKSwgMiwgbWVkaWFuKSpzZChsb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApKQpFZjQgPC0gZXhwKEVmNCkqMTAwCkVmbG9hdHMgPC0gYXBwbHkoc3Vic2V0KGRyYXdzOCwgdmFyaWFibGU9J2JldGFfZjUnKSwgMiwgbWVkaWFuKSpzZChsb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApKQpFZmxvYXRzIDwtIGV4cChFZmxvYXRzKSoxMDAKZmxvYXRzMTk4ODwtYyhtZW1vcmlhbF9kYXlzWzIwXSwgbGFib3JfZGF5c1tjKDIwLDQwKV0sIHRoYW5rc2dpdmluZ19kYXlzW2MoMjAsNDApXSktNjkzOQpFZjRmbG9hdCA8LSBFZjQKRWY0ZmxvYXRbZmxvYXRzMTk4OF0gPC0gRWY0ZmxvYXRbZmxvYXRzMTk4OF0qRWZsb2F0c1tjKDEsMiwyLDMsMyldLzEwMApwZiA8LSBkYXRhICU+JQogIG11dGF0ZShFZiA9IEVmKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9wb2ludChhZXMoeT1FZiksIGNvbG9yPXNldDFbMV0sIGFscGhhPTAuMikgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMiKQpwZjEgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYxID0gRWYxKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9saW5lKGFlcyh5PUVmMSksIGNvbG9yPXNldDFbMV0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIikKcGYyIDwtIGRhdGEgJT4lCiAgbXV0YXRlKEVmMiA9IEVmMikgJT4lCiAgZ3JvdXBfYnkoZGF5X29mX3llYXIyKSAlPiUKICBzdW1tYXJpc2UobWVhbmJpcnRocz1tZWFuKGJpcnRoc19yZWxhdGl2ZTEwMCksIG1lYW5FZjI9bWVhbihFZjIpKSAlPiUKICBnZ3Bsb3QoYWVzKHg9YXMuRGF0ZSgiMTk4Ny0xMi0zMSIpK2RheV9vZl95ZWFyMiwgeT1tZWFuYmlydGhzKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKSArCiAgZ2VvbV9saW5lKGFlcyh5PW1lYW5FZjIpLCBjb2xvcj1zZXQxWzFdKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyBvZiB5ZWFyIikKcGYzIDwtIGdncGxvdChkYXRhPWRhdGEsIGFlcyh4PWRheV9vZl93ZWVrLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gMTo3LCBsYWJlbHM9YygnTW9uJywnVHVlJywnV2VkJywnVGh1JywnRnJpJywnU2F0JywnU3VuJykpICsKICBnZW9tX2xpbmUoZGF0YT1kYXRhLmZyYW1lKHg9MTo3LHk9RWZfZGF5X29mX3dlZWspLCBhZXMoeD14LCB5PUVmX2RheV9vZl93ZWVrKSwgY29sb3I9c2V0MVsxXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgb2Ygd2VlayIpCk49bGVuZ3RoKGRhdGEkaWQpCnBmM2IgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYzID0gRWYzKkVmMS8xMDApICU+JQogIGdncGxvdChhZXMoeD1kYXRlLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBnZW9tX3BvaW50KGFlcyh5PUVmMyksIGNvbG9yPXNldDFbMV0sIHNpemU9MC4xKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg5LTA4LTAxIikseT0oRWYzKkVmMS8xMDApW2MoKE4tNSk6KE4tNCksIE4sIE4tNildLGxhYmVsPWMoIk1vbiIsIlR1ZSIsIlNhdCIsIlN1biIpKQpmMTMgPC0gZGF0YSAlPiUgZmlsdGVyKHllYXI9PTE5ODgpJT4lc2VsZWN0KGRheSxkYXRlKSU+JW11dGF0ZSh5PUVmNGZsb2F0KSU+JWZpbHRlcihkYXk9PTEzKQpwZjJiIDwtZGF0YS5mcmFtZSh4PWFzLkRhdGUoIjE5ODgtMDEtMDEiKSswOjM2NSwgeT1FZjRmbG9hdCkgJT4lCiAgZ2dwbG90KGFlcyh4PXgseT15KSkgKyBnZW9tX2xpbmUoY29sb3I9c2V0MVsxXSkgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyBvZiB5ZWFyIikgKwogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMDEtMDEiKSx5PUVmNGZsb2F0WzFdLTEsbGFiZWw9Ik5ldyB5ZWFyIikgKwogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMDItMTQiKSx5PUVmNGZsb2F0WzQ1XSsxLjUsbGFiZWw9IlZhbGVudGluZSdzIGRheSIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTAyLTI5IikseT1FZjRmbG9hdFs2MF0tMi41LGxhYmVsPSJMZWFwIGRheSIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTA0LTAxIikseT1FZjRmbG9hdFs5Ml0tMS41LGxhYmVsPSJBcHJpbCAxc3QiKSArIAogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMDctMDQiKSx5PUVmNGZsb2F0WzE4Nl0tMS41LGxhYmVsPSJJbmRlcGVuZGVuY2UgZGF5IikgKwogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMTAtMzEiKSx5PUVmNGZsb2F0WzMwNV0tMS41LGxhYmVsPSJIYWxsb3dlZW4iKSArIAogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMTItMjQiKSx5PUVmNGZsb2F0WzM2MF0tMixsYWJlbD0iQ2hyaXN0bWFzIikgKwogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMDUtMzAiKSx5PUVmNGZsb2F0WzE1MV0tMixsYWJlbD0iTWVtb3JpYWwgZGF5IikgKwogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMDktMDUiKSx5PUVmNGZsb2F0WzI0OV0tMS41LGxhYmVsPSJMYWJvciBkYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMTEtMjQiKSx5PUVmNGZsb2F0WzMyOV0tMSxsYWJlbD0iVGhhbmtzZ2l2aW5nIikrCiAgZ2VvbV9wb2ludChkYXRhPWYxMyxhZXMoeD1kYXRlLHk9eSksIHNpemU9Mywgc2hhcGU9MSkKKHBmICsgcGYxKSAvIChwZjIgKyBwZjNiKSAvIChwZjJiKQoKIycgVGhlIGluZmVyZW5jZSBmb3IgdGhlIG1vZGVsIHdvcmtzIGZpbmUsIHdoaWNoIGhpbnRzIHRoYXQgb3VyIFJIUwojJyBpbXBsZW1lbnRhdGlvbiBmb3IgdGhlIG1vZGVsIDUgd2FzIHdyb25nIG9yIGhhZCB2ZXJ5IGRpZmZpY3VsdAojJyBwb3N0ZXJpb3IuIEJlZm9yZSB0ZXN0aW5nIFJIUyBhZ2Fpbiwgd2UnbGwgdGVzdCB3aXRoIGFuIGVhc2llciB0bwojJyBpbXBsZW1lbnQgU3R1ZGVudCdzICR0JCBwcmlvciB3aGV0aGVyIGxvbmcgdGFpbGVkIHByaW9yIGZvciBkYXkgb2YKIycgeWVhciBlZmZlY3QgaXMgcmVhc29uYWJsZS4gVGhlc2UgZXhwZXJpbWVudHMgaGVscCBhbHNvIHRvIGZpbmQgb3V0CiMnIHdoZXRoZXIgdGhlIGRheSBvZiB5ZWFyIGVmZmVjdCBpcyBzZW5zaXRpdmUgdG8gdGhlIHByaW9yIGNob2ljZS4KIycKIycKIycgIyMjIE1vZGVsIDgrdF9udTogZGF5IG9mIHllYXIgZWZmZWN0IHdpdGggU3R1ZGVudCdzIHQgcHJpb3IKIycgCiMnIENvbXBpbGUgU3RhbiBtb2RlbCA4ICsgdF9udSBbZ3BiZjh0bnUuc3Rhbl0oaHR0cHM6Ly9naXRodWIuY29tL2F2ZWh0YXJpL2Nhc2VzdHVkaWVzL2Jsb2IvbWFzdGVyL0JpcnRoZGF5cy9ncGJmOHRudS5zdGFuKQojKyBtb2RlbDh0bnUsIHJlc3VsdHM9J2hpZGUnCm1vZGVsOHRudSA8LSBjbWRzdGFuX21vZGVsKHN0YW5fZmlsZSA9IHJvb3QoIkJpcnRoZGF5cyIsICJncGJmOHRudS5zdGFuIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGluY2x1ZGVfcGF0aHMgPSByb290KCJCaXJ0aGRheXMiKSkKCiMnIE9wdGltaXppbmcgaXMgZmFzdGVyIHRoYW4gc2FtcGxpbmcgKGFsdGhvdWdoIHRoaXMgcmVzdWx0IGNhbiBiZQojJyB1c2VmdWwgaW4gYSBxdWljayB3b3JrZmxvdywgdGhlIHJlc3VsdCBzaG91bGQgbm90IGJlIHVzZWQgYXMgdGhlCiMnIGZpbmFsIHJlc3VsdCkuCiMrIG9wdDh0bnUsIHJlc3VsdHM9J2hpZGUnCm9wdDh0bnUgPC0gbW9kZWw4dG51JG9wdGltaXplKGRhdGE9c3RhbmRhdGE4LCBpbml0PTAuMSwgYWxnb3JpdGhtPSdsYmZncycsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhpc3Rvcnk9MTAwLCB0b2xfb2JqPTEwKQpvZHJhd3M4dG51IDwtIG9wdDh0bnUkZHJhd3MoKQoKIycgU2FtcGxlIHNob3J0IGNoYWlucyB1c2luZyB0aGUgZWFybHkgc3RvcHBlZCBvcHRpbWl6YXRpb24gcmVzdWx0IGFzCiMnIGluaXRpYWwgdmFsdWVzIChhbHRob3VnaCB0aGUgcmVzdWx0IGZyb20gc2hvcnQgY2hhaW5zIGNhbiBiZSB1c2VmdWwKIycgaW4gYSBxdWljayB3b3JrZmxvdywgdGhlIHJlc3VsdCBzaG91bGQgbm90IGJlIHVzZWQgYXMgdGhlIGZpbmFsCiMnIHJlc3VsdCkuCmluaXQ4dG51IDwtIHNhcHBseShjKCdpbnRlcmNlcHQwJywnbGVuZ3Roc2NhbGVfZjEnLCdsZW5ndGhzY2FsZV9mMicsJ2xlbmd0aHNjYWxlX2czJywKICAgICAgICAgICAgICAgICAgJ3NpZ21hX2YxJywnc2lnbWFfZjInLCdzaWdtYV9nMycsJ3NpZ21hX2Y0JywnbnVfZjQnLCdzaWdtYScsCiAgICAgICAgICAgICAgICAgICdiZXRhX2YxJywnYmV0YV9mMicsJ2JldGFfZjMnLCdiZXRhX2czJywnYmV0YV9mNCcsJ2JldGFfZjUnKSwKICAgICAgICAgICAgICAgIGZ1bmN0aW9uKHZhcmlhYmxlKSB7YXMubnVtZXJpYyhzdWJzZXQob2RyYXdzOHRudSwgdmFyaWFibGU9dmFyaWFibGUpKX0pCiMrIGZpdDh0bnUsIHJlc3VsdHM9J2hpZGUnCmZpdDh0bnUgPC0gbW9kZWw4dG51JHNhbXBsZShkYXRhPXN0YW5kYXRhOCwgaXRlcl93YXJtdXA9MTAwLCBpdGVyX3NhbXBsaW5nPTEwMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoYWlucz00LCBwYXJhbGxlbF9jaGFpbnM9NCwKICAgICAgICAgICAgICAgICAgICAgIGluaXQ9ZnVuY3Rpb24oKSB7IGluaXQ4dG51IH0sIHJlZnJlc2g9MTApCgojJyBDaGVjayB3aGV0aGVyIHBhcmFtZXRlcnMgaGF2ZSByZWFzb25hYmxlIHZhbHVlcwpkcmF3czh0bnUgPC0gZml0OHRudSRkcmF3cygpCnN1bW1hcmlzZV9kcmF3cyhzdWJzZXQoZHJhd3M4dG51LCB2YXJpYWJsZT1jKCdpbnRlcmNlcHQnLCdzaWdtYV8nLCdsZW5ndGhzY2FsZV8nLCdzaWdtYScsJ251XycpLCByZWdleD1UUlVFKSkKIycgUG9zdGVyaW9yIG9mIGRlZ3JlZXMgb2YgZnJlZWRvbSBgbnVfZjRgIGlzIHZlcnkgY2xvc2UgdG8gMSwgYW5kCiMnIHRodXMgdGhlIGRpc3RyaWJ1dGlvbiBpcyB2ZXJ5IGNsb3NlIHRvIENhdWNoeS4gVGhpcyBpcyBzdHJvbmcKIycgZXZpZGVuY2UgdGhhdCB0aGUgZGlzdHJpYnV0aW9uIG9mIGRheSBvZiB5ZWFyIGVmZmVjdHMgaXMgZmFyIGZyb20KIycgbm9ybWFsLCBldmVuIGlmIENhdWNoeSB3b3VsZCBub3QgYmUgdGhlIGNvcnJlY3QgZGlzdHJpYnV0aW9uLgoKIycgQ29tcGFyZSB0aGUgbW9kZWwgdG8gdGhlIGRhdGEKZHJhd3M4IDwtIGFzX2RyYXdzX21hdHJpeChkcmF3czh0bnUpCkVmIDwtIGV4cChhcHBseShzdWJzZXQoZHJhd3M4LCB2YXJpYWJsZT0nZicpLCAyLCBtZWRpYW4pKQpFZjEgPC0gYXBwbHkoc3Vic2V0KGRyYXdzOCwgdmFyaWFibGU9J2YxJyksIDIsIG1lZGlhbikKRWYxIDwtIGV4cChFZjEgLSBtZWFuKEVmMSkgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZjIgPC0gYXBwbHkoc3Vic2V0KGRyYXdzOCwgdmFyaWFibGU9J2YyJyksIDIsIG1lZGlhbikKRWYyIDwtIGV4cChFZjIgLSBtZWFuKEVmMikgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZl9kYXlfb2Zfd2VlayA8LSBhcHBseShzdWJzZXQoZHJhd3M4LCB2YXJpYWJsZT0nZl9kYXlfb2Zfd2VlaycpLCAyLCBtZWRpYW4pCkVmX2RheV9vZl93ZWVrIDwtIGV4cChFZl9kYXlfb2Zfd2VlayAtIG1lYW4oRWZfZGF5X29mX3dlZWspICsgbWVhbihsb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApKSkKRWYzIDwtIGFwcGx5KHN1YnNldChkcmF3czgsIHZhcmlhYmxlPSdmMycpLCAyLCBtZWRpYW4pCkVmMyA8LSBleHAoRWYzIC0gbWVhbihFZjMpICsgbWVhbihsb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApKSkKRWY0IDwtIGFwcGx5KHN1YnNldChkcmF3czgsIHZhcmlhYmxlPSdiZXRhX2Y0JyksIDIsIG1lZGlhbikqc2QobG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkKRWY0IDwtIGV4cChFZjQpKjEwMApFZmxvYXRzIDwtIGFwcGx5KHN1YnNldChkcmF3czgsIHZhcmlhYmxlPSdiZXRhX2Y1JyksIDIsIG1lZGlhbikqc2QobG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkKRWZsb2F0cyA8LSBleHAoRWZsb2F0cykqMTAwCmZsb2F0czE5ODg8LWMobWVtb3JpYWxfZGF5c1syMF0sIGxhYm9yX2RheXNbYygyMCw0MCldLCB0aGFua3NnaXZpbmdfZGF5c1tjKDIwLDQwKV0pLTY5MzkKRWY0ZmxvYXQgPC0gRWY0CkVmNGZsb2F0W2Zsb2F0czE5ODhdIDwtIEVmNGZsb2F0W2Zsb2F0czE5ODhdKkVmbG9hdHNbYygxLDIsMiwzLDMpXS8xMDAKcGYgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYgPSBFZikgJT4lCiAgZ2dwbG90KGFlcyh4PWRhdGUsIHk9YmlydGhzX3JlbGF0aXZlMTAwKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIGdlb21fcG9pbnQoYWVzKHk9RWYpLCBjb2xvcj1zZXQxWzFdLCBhbHBoYT0wLjIpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIikKcGYxIDwtIGRhdGEgJT4lCiAgbXV0YXRlKEVmMSA9IEVmMSkgJT4lCiAgZ2dwbG90KGFlcyh4PWRhdGUsIHk9YmlydGhzX3JlbGF0aXZlMTAwKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIGdlb21fbGluZShhZXMoeT1FZjEpLCBjb2xvcj1zZXQxWzFdKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyIpCnBmMiA8LSBkYXRhICU+JQogIG11dGF0ZShFZjIgPSBFZjIpICU+JQogIGdyb3VwX2J5KGRheV9vZl95ZWFyMikgJT4lCiAgc3VtbWFyaXNlKG1lYW5iaXJ0aHM9bWVhbihiaXJ0aHNfcmVsYXRpdmUxMDApLCBtZWFuRWYyPW1lYW4oRWYyKSkgJT4lCiAgZ2dwbG90KGFlcyh4PWFzLkRhdGUoIjE5ODctMTItMzEiKStkYXlfb2ZfeWVhcjIsIHk9bWVhbmJpcnRocykpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikgKwogIGdlb21fbGluZShhZXMoeT1tZWFuRWYyKSwgY29sb3I9c2V0MVsxXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgb2YgeWVhciIpCnBmMyA8LSBnZ3Bsb3QoZGF0YT1kYXRhLCBhZXMoeD1kYXlfb2Zfd2VlaywgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IDE6NywgbGFiZWxzPWMoJ01vbicsJ1R1ZScsJ1dlZCcsJ1RodScsJ0ZyaScsJ1NhdCcsJ1N1bicpKSArCiAgZ2VvbV9saW5lKGRhdGE9ZGF0YS5mcmFtZSh4PTE6Nyx5PUVmX2RheV9vZl93ZWVrKSwgYWVzKHg9eCwgeT1FZl9kYXlfb2Zfd2VlayksIGNvbG9yPXNldDFbMV0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIG9mIHdlZWsiKQpOPWxlbmd0aChkYXRhJGlkKQpwZjNiIDwtIGRhdGEgJT4lCiAgbXV0YXRlKEVmMyA9IEVmMypFZjEvMTAwKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9wb2ludChhZXMoeT1FZjMpLCBjb2xvcj1zZXQxWzFdLCBzaXplPTAuMSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMiKSArCiAgYW5ub3RhdGUoInRleHQiLHg9YXMuRGF0ZSgiMTk4OS0wOC0wMSIpLHk9KEVmMypFZjEvMTAwKVtjKChOLTUpOihOLTQpLCBOLCBOLTYpXSxsYWJlbD1jKCJNb24iLCJUdWUiLCJTYXQiLCJTdW4iKSkKZjEzIDwtIGRhdGEgJT4lIGZpbHRlcih5ZWFyPT0xOTg4KSU+JXNlbGVjdChkYXksZGF0ZSklPiVtdXRhdGUoeT1FZjRmbG9hdCklPiVmaWx0ZXIoZGF5PT0xMykKCnBmMmIgPC1kYXRhLmZyYW1lKHg9YXMuRGF0ZSgiMTk4OC0wMS0wMSIpKzA6MzY1LCB5PUVmNGZsb2F0KSAlPiUKICBnZ3Bsb3QoYWVzKHg9eCx5PXkpKSArIGdlb21fbGluZShjb2xvcj1zZXQxWzFdKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCBkYXRlX2xhYmVscyA9ICIlYiIpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIG9mIHllYXIiKSArCiAgYW5ub3RhdGUoInRleHQiLHg9YXMuRGF0ZSgiMTk4OC0wMS0wMSIpLHk9RWY0ZmxvYXRbMV0tMSxsYWJlbD0iTmV3IHllYXIiKSArCiAgYW5ub3RhdGUoInRleHQiLHg9YXMuRGF0ZSgiMTk4OC0wMi0xNCIpLHk9RWY0ZmxvYXRbNDVdKzEuNSxsYWJlbD0iVmFsZW50aW5lJ3MgZGF5IikgKwogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMDItMjkiKSx5PUVmNGZsb2F0WzYwXS0yLjUsbGFiZWw9IkxlYXAgZGF5IikgKwogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMDQtMDEiKSx5PUVmNGZsb2F0WzkyXS0xLjUsbGFiZWw9IkFwcmlsIDFzdCIpICsgCiAgYW5ub3RhdGUoInRleHQiLHg9YXMuRGF0ZSgiMTk4OC0wNy0wNCIpLHk9RWY0ZmxvYXRbMTg2XS0xLjUsbGFiZWw9IkluZGVwZW5kZW5jZSBkYXkiKSArCiAgYW5ub3RhdGUoInRleHQiLHg9YXMuRGF0ZSgiMTk4OC0xMC0zMSIpLHk9RWY0ZmxvYXRbMzA1XS0xLjUsbGFiZWw9IkhhbGxvd2VlbiIpICsgCiAgYW5ub3RhdGUoInRleHQiLHg9YXMuRGF0ZSgiMTk4OC0xMi0yNCIpLHk9RWY0ZmxvYXRbMzYwXS0yLGxhYmVsPSJDaHJpc3RtYXMiKSArCiAgYW5ub3RhdGUoInRleHQiLHg9YXMuRGF0ZSgiMTk4OC0wNS0zMCIpLHk9RWY0ZmxvYXRbMTUxXS0yLGxhYmVsPSJNZW1vcmlhbCBkYXkiKSArCiAgYW5ub3RhdGUoInRleHQiLHg9YXMuRGF0ZSgiMTk4OC0wOS0wNSIpLHk9RWY0ZmxvYXRbMjQ5XS0xLjUsbGFiZWw9IkxhYm9yIGRheSIpICsgCiAgYW5ub3RhdGUoInRleHQiLHg9YXMuRGF0ZSgiMTk4OC0xMS0yNCIpLHk9RWY0ZmxvYXRbMzI5XS0xLGxhYmVsPSJUaGFua3NnaXZpbmciKSsKICBnZW9tX3BvaW50KGRhdGE9ZjEzLGFlcyh4PWRhdGUseT15KSwgc2l6ZT0zLCBzaGFwZT0xKQoocGYgKyBwZjEpIC8gKHBmMiArIHBmM2IpIC8gKHBmMmIpCgojJyBUaGUgb3RoZXIgZWZmZWN0cyBzZWVtIHRvIGJlIHF1aXRlIHNpbWlsYXIgYXMgd2l0aCB0aGUgcHJldmlvdXMKIycgbW9kZWwsIGJ1dCB0aGUgZGF5IG9mIHllYXIgZWZmZWN0cyBhcmUgY2xlYXJseSBkaWZmZXJlbnQgd2l0aCBtb3N0CiMnIGRheXMgaGF2aW5nIG5vbi1kZXRlY3RhYmxlIGVmZmVjdC4gVGhlcmUgYXJlIGFsc28gZWZmZWN0cyB0aGF0CiMnIHNlZW1lZCB0byBiZSBxdWl0ZSBjbGVhciBpbiBub3JtYWwgcHJpb3IgbW9kZWwgc3VjaCBhcyAxM3RoIGRheSBvZgojJyBtb250aCBlZmZlY3QsIHdoaWNoIGlzIG5vdCB2aXNpYmxlIGFueW1vcmUuIEFzIHRoZSBwb3N0ZXJpb3Igb2YKIycgZGVncmVlcyBvZiBmcmVlZG9tIGB0X251YCB3YXMgY29uY2VudHJhdGVkIGNsb3NlIHRvIDEsIGl0J3MgbGlrZWx5CiMnIHRoYXQgdGhlIG5vcm1hbCBwcmlvciBmb3IgZGF5IG9mIHllYXIgZWZmZWN0IGNhbid0IGJlIHRoZSBiZXN0LiBTbwojJyBmYXIgd2UgaGFkbid0IHVzZWQgbW9kZWwgY29tcGFyaXNvbiBzdWNoIGFzIGxlYXZlLW9uZS1vdXQKIycgY3Jvc3MtdmFsaWRhdGlvbiAoTE9PLUNWKSBhcyBlYWNoIGFkZGVkIGNvbXBvbmVudCBoYWQgcXVhbGl0YXRpdmVseQojJyBiaWcgYW5kIHJlYXNvbmFibGUgZWZmZWN0LiBOb3cgYXMgZGF5IG9mIHllYXIgZWZmZWN0IGlzIHNlbnNpdGl2ZQojJyB0byBwcmlvciBjaG9pY2UsIGJ1dCBpdCdzIG5vdCBjbGVhciBob3cgbXVjaCBiZXR0ZXIgQ2F1Y2h5IHByaW9yCiMnIGRpc3RyaWJ1dGlvbiBpcyB3ZSB1c2UgTE9PLUNWIHRvIGNvbXBhcmUgdGhlIG1vZGVscy4KbG9vOCA8LSBmaXQ4JGxvbygpCmxvbzh0bnUgPC0gZml0OHRudSRsb28oKQpsb29fY29tcGFyZShsaXN0KGBNb2RlbCA4IG5vcm1hbGA9bG9vOCxgTW9kZWwgOCBTdHVkZW50XCdzIHRgPWxvbzh0bnUpKQojJyBBcyB3ZSBjb3VsZCBoYXZlIGV4cGVjdGVkIGJhc2VkIG9uIHRoZSBwb3N0ZXJpb3Igb2YgYG51X2Y0YAojJyBTdHVkZW50J3MgdCBwcmlvciBvbiBkYXkgb2YgeWVhciBlZmZlY3RzIGlzIGJldHRlci4gQXMgbG93IGRlZ3JlZXMKIycgb2YgZnJlZWRvbSBpbmRpY2F0ZSBhIHRoaWNrIHRhaWxlZCBkaXN0cmlidXRpb24gZm9yIGRheSBvZiB5ZWFyCiMnIGVmZmVjdCBpcyBuZWVkZWQsIHdlIGRlY2lkZWQgdG8gdGVzdCBhZ2FpbiBSSFMgcHJpb3IuCiMnIAoKIycgIyMjIE1vZGVsIDgrUkhTOiBkYXkgb2YgeWVhciBlZmZlY3Qgd2l0aCBSSFMgcHJpb3IKIycKIycgTW9kZWwgNSBoYWQgUkhTIHByaW9yIGJ1dCB0aGUgcHJvYmxlbSB3YXMgdGhhdCBvcHRpbWl6YXRpb24gcmVzdWx0CiMnIHdhc24ndCBldmVuIGNsb3NlIHRvIHNlbnNpYmxlIGFuZCBNQ01DIHdhcyB2ZXJ5IHNsb3cuIEdpdmVuIHRoZQojJyBvdGhlciBtb2RlbHMgd2Ugbm93IGtub3cgdGhhdCB0aGUgcHJvYmxlbSBpcyBub3QgaW4gYWRkaW5nIGRheSBvZgojJyB5ZWFyIGVmZmVjdCBvciBjb21iaW5pbmcgaXQgd2l0aCB0aW1lIGRlcGVuZGVudCBtYWduaXR1ZGUgZm9yIHRoZQojJyBkYXkgb2Ygd2VlayBlZmZlY3QuIEl0IHdhcyBlYXNpZXIgbm93IHRvIGZvY3VzIG9uIGZpZ3VyaW5nIG91dCB0aGUKIycgcHJvYmxlbSBpbiBSSFMuIFNpbmNlIFJIUyBpcyBwcmVzZW50ZWQgYXMgYSBzY2FsZSBtaXh0dXJlIG9mCiMnIG5vcm1hbHMgaW52b2x2aW5nIGhpZXJhcmNoaWNhbCBwcmlvciwgaXQgaXMgY29tbW9uIHRvIHVzZQojJyBub24tY2VudGVyZWQgcGFyYW1ldGVyaXphdGlvbiBmb3IgUkhTIHByaW9yLiBOb24tY2VudGVyZWQKIycgcGFyYW1ldGVyaXphdGlvbiBpcyB1c2VmdWwgd2hlbiB0aGUgaW5mb3JtYXRpb24gZnJvbSB0aGUgbGlrZWxpaG9vZAojJyBpcyB3ZWFrIGFuZCB0aGUgcHJpb3IgZGVwZW5kZW5jeSBkb21pbmF0ZXMgaW4gdGhlIHBvc3RlcmlvcgojJyBkZXBlbmRlbmN5LiBSSFMgaXMgb2Z0ZW4gdXNlZCB3aGVuIHRoZXJlIGFyZSBsZXNzIG9ic2VydmF0aW9ucyB0aGFuCiMnIHVua25vd25zLiBJbiB0aGlzIHByb2JsZW0gZWFjaCB1bmtub3duIChvbmUgZGF5IG9mIHllYXIgZWZmZWN0KSBpcwojJyBpbmZvcm1lZCBieSBzZXZlcmFsIG9ic2VydmF0aW9ucyBmcm9tIGRpZmZlcmVudCB5ZWFycywgYW5kIHRoZW4gaXQKIycgbWlnaHQgYmUgdGhhdCB0aGUgY2VudGVyZWQgcGFyYW1ldGVyaXphdGlvbiBpcyBiZXR0ZXIuIEFuZCB0aGlzCiMnIHR1cm5lZCBvdXQgdG8gYmUgdHJ1ZSBhbmQgdGhlIGluZmVyZW5jZSBmb3IgbW9kZWwgOCB3aXRoIGNlbnRlcmVkCiMnIHBhcmFtZXRlcml6YXRpb24gUkhTIHByaW9yIG9uIGRheSBvZiB5ZWFyIGVmZmVjdCB3b3JrZWQgbXVjaCBiZXR0ZXIKIycgdGhhbiBmb3IgbW9kZWwgNS4gIChJbiBTdGFuIGl0IHdhcyBlYXN5IHRvIHRlc3Qgc3dpdGNoIGZyb20KIycgbm9uLWNlbnRlcmVkIHRvIGNlbnRlcmVkIHBhcmFtZXRlcml6YXRpb24gYnkgcmVtb3ZpbmcgdGhlIG11bHRwbGllcgojJyBmcm9tIG9uZSBvZiB0aGUgcGFyYW1ldGVyIGRlY2xhcmF0aW9ucykuCiMnCiMnIENvbXBpbGUgU3RhbiBtb2RlbCA4ICsgUkhTIFtncGJmOHJocy5zdGFuXShodHRwczovL2dpdGh1Yi5jb20vYXZlaHRhcmkvY2FzZXN0dWRpZXMvYmxvYi9tYXN0ZXIvQmlydGhkYXlzL2dwYmY4cmhzLnN0YW4pCiMrIG1vZGVsOHJocywgcmVzdWx0cz0naGlkZScKbW9kZWw4cmhzIDwtIGNtZHN0YW5fbW9kZWwoc3Rhbl9maWxlID0gcm9vdCgiQmlydGhkYXlzIiwgImdwYmY4cmhzLnN0YW4iKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5jbHVkZV9wYXRocyA9IHJvb3QoIkJpcnRoZGF5cyIpKQoKIycgQWRkIGEgZ2xvYmFsIHNjYWxlIGZvciBSSFMgcHJpb3IKc3RhbmRhdGE4IDwtIGMoc3RhbmRhdGE4LAogICAgICAgICAgICAgICBzY2FsZV9nbG9iYWw9MC4xKSAjIGdsb2JhbCBzY2FsZSBmb3IgUkhTIHByaW9yCgojJyBPcHRpbWl6aW5nIGlzIGZhc3RlciB0aGFuIHNhbXBsaW5nIChhbHRob3VnaCB0aGlzIHJlc3VsdCBjYW4gYmUKIycgdXNlZnVsIGluIGEgcXVpY2sgd29ya2Zsb3csIHRoZSByZXN1bHQgc2hvdWxkIG5vdCBiZSB1c2VkIGFzIHRoZQojJyBmaW5hbCByZXN1bHQpLgojKyBvcHQ4cmhzLCByZXN1bHRzPSdoaWRlJwpvcHQ4cmhzIDwtIG1vZGVsOHJocyRvcHRpbWl6ZShkYXRhPXN0YW5kYXRhOCwgaW5pdD0wLjEsIGFsZ29yaXRobT0nbGJmZ3MnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoaXN0b3J5PTEwMCwgdG9sX29iaj0xMCkKb2RyYXdzOHJocyA8LSBvcHQ4cmhzJGRyYXdzKCkKCiMnIFNhbXBsZSBzaG9ydCBjaGFpbnMgdXNpbmcgdGhlIG9wdGltaXphdGlvbiByZXN1bHQgYXMgaW5pdGlhbCB2YWx1ZXMKIycgKGFsdGhvdWdoIHRoZSByZXN1bHQgZnJvbSBzaG9ydCBjaGFpbnMgY2FuIGJlIHVzZWZ1bCBpbiBhIHF1aWNrCiMnIHdvcmtmbG93LCB0aGUgcmVzdWx0IHNob3VsZCBub3QgYmUgdXNlZCBhcyB0aGUgZmluYWwgcmVzdWx0KS4KaW5pdDhyaHMgPC0gc2FwcGx5KGMoJ2ludGVyY2VwdDAnLCdsZW5ndGhzY2FsZV9mMScsJ2xlbmd0aHNjYWxlX2YyJywnbGVuZ3Roc2NhbGVfZzMnLAogICAgICAgICAgICAgICAgICAnc2lnbWFfZjEnLCdzaWdtYV9mMicsJ3NpZ21hX2czJywnc2lnbWFfZjQnLCdzaWdtYScsCiAgICAgICAgICAgICAgICAgICdiZXRhX2YxJywnYmV0YV9mMicsJ2JldGFfZjMnLCdiZXRhX2czJywnYmV0YV9mNCcsJ2JldGFfZjUnLAogICAgICAgICAgICAgICAgICAndGF1X2Y0JywnbGFtYmRhX2Y0JywnY2F1eF9mNCcpLAogICAgICAgICAgICAgICAgZnVuY3Rpb24odmFyaWFibGUpIHthcy5udW1lcmljKHN1YnNldChvZHJhd3M4cmhzLCB2YXJpYWJsZT12YXJpYWJsZSkpfSkKIysgZml0OHJocywgcmVzdWx0cz0naGlkZScKZml0OHJocyA8LSBtb2RlbDhyaHMkc2FtcGxlKGRhdGE9c3RhbmRhdGE4LCBpdGVyX3dhcm11cD0xMDAsIGl0ZXJfc2FtcGxpbmc9MTAwLCBjaGFpbnM9NCwgcGFyYWxsZWxfY2hhaW5zPTQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbml0PWZ1bmN0aW9uKCkgeyBpbml0OHJocyB9LCByZWZyZXNoPTEwKQoKIycgQ2hlY2sgd2hldGhlciBwYXJhbWV0ZXJzIGhhdmUgcmVhc29uYWJsZSB2YWx1ZXMKZHJhd3M4cmhzIDwtIGZpdDhyaHMkZHJhd3MoKQpzdW1tYXJpc2VfZHJhd3Moc3Vic2V0KGRyYXdzOHJocywgdmFyaWFibGU9YygnaW50ZXJjZXB0Jywnc2lnbWFfJywnbGVuZ3Roc2NhbGVfJywnc2lnbWEnLCdudV8nKSwgcmVnZXg9VFJVRSkpCgojJyBDb21wYXJlIHRoZSBtb2RlbCB0byB0aGUgZGF0YQpkcmF3czggPC0gYXNfZHJhd3NfbWF0cml4KGRyYXdzOHJocykKRWYgPC0gZXhwKGFwcGx5KHN1YnNldChkcmF3czgsIHZhcmlhYmxlPSdmJyksIDIsIG1lZGlhbikpCkVmMSA8LSBhcHBseShzdWJzZXQoZHJhd3M4LCB2YXJpYWJsZT0nZjEnKSwgMiwgbWVkaWFuKQpFZjEgPC0gZXhwKEVmMSAtIG1lYW4oRWYxKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCkVmMiA8LSBhcHBseShzdWJzZXQoZHJhd3M4LCB2YXJpYWJsZT0nZjInKSwgMiwgbWVkaWFuKQpFZjIgPC0gZXhwKEVmMiAtIG1lYW4oRWYyKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCkVmX2RheV9vZl93ZWVrIDwtIGFwcGx5KHN1YnNldChkcmF3czgsIHZhcmlhYmxlPSdmX2RheV9vZl93ZWVrJyksIDIsIG1lZGlhbikKRWZfZGF5X29mX3dlZWsgPC0gZXhwKEVmX2RheV9vZl93ZWVrIC0gbWVhbihFZl9kYXlfb2Zfd2VlaykgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZjMgPC0gYXBwbHkoc3Vic2V0KGRyYXdzOCwgdmFyaWFibGU9J2YzJyksIDIsIG1lZGlhbikKRWYzIDwtIGV4cChFZjMgLSBtZWFuKEVmMykgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZjQgPC0gYXBwbHkoc3Vic2V0KGRyYXdzOCwgdmFyaWFibGU9J2JldGFfZjQnKSwgMiwgbWVkaWFuKSpzZChsb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApKQpFZjQgPC0gZXhwKEVmNCkqMTAwCkVmbG9hdHMgPC0gYXBwbHkoc3Vic2V0KGRyYXdzOCwgdmFyaWFibGU9J2JldGFfZjUnKSwgMiwgbWVkaWFuKSpzZChsb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApKQpFZmxvYXRzIDwtIGV4cChFZmxvYXRzKSoxMDAKZmxvYXRzMTk4ODwtYyhtZW1vcmlhbF9kYXlzWzIwXSwgbGFib3JfZGF5c1tjKDIwLDQwKV0sIHRoYW5rc2dpdmluZ19kYXlzW2MoMjAsNDApXSktNjkzOQpFZjRmbG9hdCA8LSBFZjQKRWY0ZmxvYXRbZmxvYXRzMTk4OF0gPC0gRWY0ZmxvYXRbZmxvYXRzMTk4OF0qRWZsb2F0c1tjKDEsMiwyLDMsMyldLzEwMApwZiA8LSBkYXRhICU+JQogIG11dGF0ZShFZiA9IEVmKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9wb2ludChhZXMoeT1FZiksIGNvbG9yPXNldDFbMV0sIGFscGhhPTAuMikgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMiKQpwZjEgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYxID0gRWYxKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9saW5lKGFlcyh5PUVmMSksIGNvbG9yPXNldDFbMV0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIikKcGYyIDwtIGRhdGEgJT4lCiAgbXV0YXRlKEVmMiA9IEVmMikgJT4lCiAgZ3JvdXBfYnkoZGF5X29mX3llYXIyKSAlPiUKICBzdW1tYXJpc2UobWVhbmJpcnRocz1tZWFuKGJpcnRoc19yZWxhdGl2ZTEwMCksIG1lYW5FZjI9bWVhbihFZjIpKSAlPiUKICBnZ3Bsb3QoYWVzKHg9YXMuRGF0ZSgiMTk4Ny0xMi0zMSIpK2RheV9vZl95ZWFyMiwgeT1tZWFuYmlydGhzKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKSArCiAgZ2VvbV9saW5lKGFlcyh5PW1lYW5FZjIpLCBjb2xvcj1zZXQxWzFdKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyBvZiB5ZWFyIikKcGYzIDwtIGdncGxvdChkYXRhPWRhdGEsIGFlcyh4PWRheV9vZl93ZWVrLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gMTo3LCBsYWJlbHM9YygnTW9uJywnVHVlJywnV2VkJywnVGh1JywnRnJpJywnU2F0JywnU3VuJykpICsKICBnZW9tX2xpbmUoZGF0YT1kYXRhLmZyYW1lKHg9MTo3LHk9RWZfZGF5X29mX3dlZWspLCBhZXMoeD14LCB5PUVmX2RheV9vZl93ZWVrKSwgY29sb3I9c2V0MVsxXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgb2Ygd2VlayIpCk49bGVuZ3RoKGRhdGEkaWQpCnBmM2IgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYzID0gRWYzKkVmMS8xMDApICU+JQogIGdncGxvdChhZXMoeD1kYXRlLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBnZW9tX3BvaW50KGFlcyh5PUVmMyksIGNvbG9yPXNldDFbMV0sIHNpemU9MC4xKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg5LTA4LTAxIikseT0oRWYzKkVmMS8xMDApW2MoKE4tNSk6KE4tNCksIE4sIE4tNildLGxhYmVsPWMoIk1vbiIsIlR1ZSIsIlNhdCIsIlN1biIpKQpmMTMgPC0gZGF0YSAlPiUgZmlsdGVyKHllYXI9PTE5ODgpJT4lc2VsZWN0KGRheSxkYXRlKSU+JW11dGF0ZSh5PUVmNGZsb2F0KSU+JWZpbHRlcihkYXk9PTEzKQoKcGYyYiA8LWRhdGEuZnJhbWUoeD1hcy5EYXRlKCIxOTg4LTAxLTAxIikrMDozNjUsIHk9RWY0ZmxvYXQpICU+JQogIGdncGxvdChhZXMoeD14LHk9eSkpICsgZ2VvbV9saW5lKGNvbG9yPXNldDFbMV0pICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgb2YgeWVhciIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTAxLTAxIikseT1FZjRmbG9hdFsxXS0xLGxhYmVsPSJOZXcgeWVhciIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTAyLTE0IikseT1FZjRmbG9hdFs0NV0rMS41LGxhYmVsPSJWYWxlbnRpbmUncyBkYXkiKSArCiAgYW5ub3RhdGUoInRleHQiLHg9YXMuRGF0ZSgiMTk4OC0wMi0yOSIpLHk9RWY0ZmxvYXRbNjBdLTIuNSxsYWJlbD0iTGVhcCBkYXkiKSArCiAgYW5ub3RhdGUoInRleHQiLHg9YXMuRGF0ZSgiMTk4OC0wNC0wMSIpLHk9RWY0ZmxvYXRbOTJdLTEuNSxsYWJlbD0iQXByaWwgMXN0IikgKyAKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTA3LTA0IikseT1FZjRmbG9hdFsxODZdLTEuNSxsYWJlbD0iSW5kZXBlbmRlbmNlIGRheSIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTEwLTMxIikseT1FZjRmbG9hdFszMDVdLTEuNSxsYWJlbD0iSGFsbG93ZWVuIikgKyAKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTEyLTI0IikseT1FZjRmbG9hdFszNjBdLTIsbGFiZWw9IkNocmlzdG1hcyIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTA1LTMwIikseT1FZjRmbG9hdFsxNTFdLTIsbGFiZWw9Ik1lbW9yaWFsIGRheSIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTA5LTA1IikseT1FZjRmbG9hdFsyNDldLTEuNSxsYWJlbD0iTGFib3IgZGF5IikgKyAKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTExLTI0IikseT1FZjRmbG9hdFszMjldLTEsbGFiZWw9IlRoYW5rc2dpdmluZyIpKwogIGdlb21fcG9pbnQoZGF0YT1mMTMsYWVzKHg9ZGF0ZSx5PXkpLCBzaXplPTMsIHNoYXBlPTEpCihwZiArIHBmMSkgLyAocGYyICsgcGYzYikgLyAocGYyYikKCiMnIFZpc3VhbGx5IHdlIGdldCBxdWl0ZSBzaW1pbGFyIHJlc3VsdCBhcyB3aXRoIENhdWNoeSBwcmlvci4gV2hlbiB3ZQojJyBjb21wYXJlIHRoZSBtb2RlbHMgd2l0aCBMT08tQ1YsIENhdWNoeSBpcyBmYXZvcmVkIGluc3RlYWQgb2YgUkhTLgpsb284cmhzPC1maXQ4cmhzJGxvbygpCmxvb19jb21wYXJlKGxpc3QoYE1vZGVsIDggU3R1ZGVudHMgdGA9bG9vOHRudSxgTW9kZWwgOCBSSFNgPWxvbzhyaHMpKQojJyBJZiB3ZSBsb29rIGF0IHRoZSBMT08tc3RhY2tpbmcgbW9kZWwgd2VpZ2h0cywgdGhlIHByZWRpY3RpdmUKIycgcGVyZm9ybWFuY2UgY2FuIGJlIGltcHJvdmVkIGJ5IGNvbWJpbmluZyBDYXVjaHkgYW5kIFJIUyBwcmlvcnMgb24KIycgZGF5IG9mIHllYXIgZWZmZWN0IHdoaWNoIGluZGljYXRlcyB0aGF0IG5laXRoZXIgb2YgdGhlbSBpcyB2ZXJ5CiMnIGNsb3NlIHRvIHRydWUgZGlzdHJpYnV0aW9uLgpsb29fbW9kZWxfd2VpZ2h0cyhsaXN0KGBNb2RlbCA4IFN0dWRlbnRzIHRgPWxvbzh0bnUsYE1vZGVsIDggUkhTYD1sb284cmhzKSkKCiMnICMjIyBGdXJ0aGVyIGltcHJvdmVtZW50cyBmb3IgdGhlIGRheSBvZiB5ZWFyIGVmZmVjdAojJyAKIycgSXQncyB1bmxpa2VseSB0aGF0IGRheSBvZiB5ZWFyIGVmZmVjdCB3b3VsZCBiZSB1bnN0cnVjdHVyZWQgd2l0aAojJyBzb21lIGRpc3RyaWJ1dGlvbiBsaWtlIENhdWNoeSwgYW5kIHRodXMgaW5zdGVhZCBvZiB0cnlpbmcgdG8gZmluZCBhCiMnIHByaW9yIGRpc3RyaWJ1dGlvbiB0aGF0IHdvdWxkIGltcHJvdmUgTE9PLUNWLCBpdCB3b3VsZCBtYWtlIG1vcmUKIycgc2Vuc2UgdG8gZnVydGhlciBhZGQgc3RydWN0dXJhbCBpbmZvcm1hdGlvbi4gRm9yIGV4YW1wbGUsIGl0IHdvdWxkCiMnIGJlIHBvc3NpYmxlIHRvIGFkZCBtb3JlIGtub3duIHNwZWNpYWwgZGF5cyBhbmQgdGFrZSBpbnRvIGFjY291bnQKIycgdGhhdCBhIHNwZWNpYWwgZGF5IGVmZmVjdCBhbmQgd2Vla2VuZCBlZmZlY3QgcHJvYmFibHkgYXJlIG5vdAojJyBhZGRpdGl2ZS4gRnVydGhlcm1vcmUgaWYgdGhlcmUgYXJlIGxlc3MgYmlydGhzIGR1cmluZyBzb21lIGRheSwgdGhlCiMnIGJpcnRocyBuZWVkIHRvIGhhcHBlbiBzb21lIG90aGVyIGRheSBhbmQgaXQgY2FuIGJlIGFzc3VtZWQgdGhhdAojJyB0aGVyZSB3b3VsZCBiZSBjb3JyZXNwb25kaW5nIGV4Y2VzcyBvZiBiaXJ0aHMgYmVmb3JlIG9mIGFmdGVyIGEKIycgYmFuayBob2xpZGF5LiBUaGlzIHJpbmdpbmcgYXJvdW5kIGRheXMgd2l0aCBsZXNzIGJpcnRocyBpcyBub3QKIycgc2ltcGxlIGFzIGl0IGlzIGFsc28gYWZmZWN0ZWQgd2hldGhlciB0aGUgcHJldmlvdXMgYW5kIGZvbGxvd2luZwojJyBkYXlzIGFyZSB3ZWVrZW5kIGRheXMuIFRoaXMgYWxsIGdldHMgbW9yZSBjb21wbGljYXRlZCB0aGFuIHdlIHdhbnQKIycgdG8gaW5jbHVkZSBpbiB0aGlzIGNhc2Ugc3R1ZHksIGJ1dCB0aGUgcmVhZGVyIGNhbiBzZWUgaG93IHRoZQojJyBzaW1pbGFyIGdyYWR1YWwgbW9kZWwgYnVpbGRpbmcgY291bGQgYmUgbWFkZSBieSBhZGRpbmcgYWRkaXRpb25hbAojJyBjb21wb25lbnRzLiBFdmVudHVhbGx5IGl0IGlzIGxpa2VseSB0aGF0IHRoZXJlIHN0YXJ0cyB0byBiZSB3b3JyeQojJyBvZiBvdmVyZml0dGluZywgYnV0IGludGVncmF0aW9uIG92ZXIgdGhlIHVua25vd24gYWxsZXZpYXRlcyB0aGF0CiMnIGFuZCBsb29raW5nIGF0IHRoZSBwcmVkaWN0aXZlIHBlcmZvcm1hbmNlIGVzdGltYXRlcyBzdWNoIExPTy1DViBjYW4KIycgaGVscCB0byBkZWNpZGUgd2hlbiB0aGUgYWRkaXRpb25hbCBtb2RlbCBjb21wb25lbnRzIGRvbid0IGltcHJvdmUKIycgdGhlIHByZWRpY3RpdmUgcGVyZm9ybWFuY2Ugb3IgY2FuJ3QgYmUgd2VsbCBpZGVudGlmaWVkLgojJwojJyAjIyMgUXVhbnRpdGF0aXZlIHByZWRpY3RpdmUgcGVyZm9ybWFuY2UgZm9yIHRoZSBzZXJpZXMgb2YgbW9kZWxzCiMnIAojJyBXZSBkaWRuJ3QgdXNlIExPTy1DViB1bnRpbCBpbiB0aGUgZW5kLCBhcyB0aGUgcXVhbGl0YXRpdmUKIycgZGlmZmVyZW5jZXMgYmV0d2VlbiBtb2RlbHMgd2VyZSB2ZXJ5IGNvbnZpbmNpbmcuIFdlIGNhbiB1c2UgTE9PLUNWCiMnIHRvIGNoZWNrIGhvdyBiaWcgdGhlIGRpZmZlcmVuY2UgaW4gdGhlIHByZWRpY3RpdmUgcGVyZm9ybWFuY2UgYXJlCiMnIGFuZCBpZiB0aGUgZGlmZmVyZW5jZXMgYXJlIGJpZywgd2Uga25vdyB0aGF0IG1vZGVsIGF2ZXJhZ2luZyB0aGF0CiMnIHdvdWxkIHRha2UgaW50byBhY2NvdW50IHRoZSB1bmNlcnRhaW50eSB3b3VsZCBnaXZlIHdlaWdodHMgY2xvc2UgdG8KIycgemVybyBmb3IgYWxsIGJ1dCB0aGUgbW9zdCBlbGFib3JhdGUgbW9kZWxzLgpsb28xPC1maXQxJGxvbygpCmxvbzI8LWZpdDIkbG9vKCkKbG9vMzwtZml0MyRsb28oKQpsb280PC1maXQ0JGxvbygpCmxvbzY8LWZpdDYkbG9vKCkKbG9vNzwtZml0NyRsb28oKQpsb29fY29tcGFyZShsaXN0KGBNb2RlbCAxYD1sb28xLGBNb2RlbCAyYD1sb28yLGBNb2RlbCAzYD1sb28zLGBNb2RlbCA0YD1sb280LGBNb2RlbCA2YD1sb282LGBNb2RlbCA3YD1sb283LGBNb2RlbCA4ICsgdF9udWA9bG9vOHRudSkpCgojJyAjIyMgUmVzaWR1YWwgYW5hbHlzaXMKIycgCiMnIFdlIGNhbiBnZXQgZnVydGhlciBpZGVhcyBmb3IgaG93IHRvIGltcHJvdmUgdGhlIG1vZGVsIGFsc28gYnkKIycgbG9va2luZyBhdCB0aGUgcmVzaWR1YWxzLgpkcmF3czggPC0gYXNfZHJhd3NfbWF0cml4KGRyYXdzOHRudSkKRWYgPC0gZXhwKGFwcGx5KHN1YnNldChkcmF3czgsIHZhcmlhYmxlPSdmJyksIDIsIG1lZGlhbikpCmRhdGEgJT4lCiAgbXV0YXRlKEVmID0gRWYpICU+JQogIGdncGxvdChhZXMoeD1kYXRlLCB5PWxvZyhiaXJ0aHNfcmVsYXRpdmUxMDAvRWYpKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MCwgY29sb3I9J2dyYXknKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gIjEgeWVhciIsIGRhdGVfbGFiZWxzID0gIiVZIikgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueD1lbGVtZW50X2xpbmUoY29sb3I9J2dyYXknLHNpemU9MSkpCiMnIFdlIGNhbiBzZWUgc29tZSBzdHJ1Y3R1cmUsIHNwZWNpZmljYWxseSBpbiB5ZWFycyAxOTY5LS0xOTc4IHRoZQojJyByZXNpZHVhbCBoYXMgbmVnYXRpdmUgcGVhayBpbiB0aGUgbWlkZGxlIG9mIHRoZSB5ZWFyLCB3aGlsZSBpbiB5ZWFycwojJyAxOTgxLS0xOTg4IHRoZSByZXNpZHVhbCBoYXMgcG9zaXRpdmUgcGVhayBpbiB0aGUgbWlkZGxlIG9mIHRoZQojJyB5ZWFyLiBUaGlzIGtpbmQgb2YgcGF0dGVybiBhcHBlYXJzIGFzIHdlIHVzZSB0aGUgc2FtZSBzZWFzb25hbAojJyBlZmZlY3QgZm9yIGFsbCB5ZWFycywgYnV0IHRoZSBtYWduaXR1ZGUgb2Ygc2Vhc29uYWwgZWZmZWN0IGlzCiMnIGNoYW5naW5nLiBJdCB3b3VsZCBiZSBwb3NzaWJsZSB0byBtb2RpZnkgdGhlIG1vZGVsIHRvIGluY2x1ZGUKIycgZ3JhZHVhbGx5IGNoYW5naW5nIHNlYXNvbmFsIGVmZmVjdCwgYnV0IGxlYXZlIGl0IG91dCBmcm9tIHRoaXMgY2FzZQojJyBzdHVkeS4gCiMnCiMnIFRoZSBiZXN0IG1vZGVsIHNvIGZhciBleHBsYWlucyBhbHJlYWR5IDk0JSBvZiB0aGUgdmFyaWFuY2UgKExPTy1SMikuCmRyYXdzOCA8LSBhc19kcmF3c19tYXRyaXgoZHJhd3M4dG51KQpmIDwtIGV4cChzdWJzZXQoZHJhd3M4LCB2YXJpYWJsZT0nZicpKQpsb284dG51IDwtIGZpdDh0bnUkbG9vKHNhdmVfcHNpcz1UUlVFKQpFZmxvbyA8LSBFX2xvbyhmLCBwc2lzX29iamVjdD1sb284dG51JHBzaXNfb2JqZWN0KSR2YWx1ZQpMT09SMiA8LSAxLXZhcihsb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDAvRWZsb28pKS92YXIobG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkKcHJpbnQoTE9PUjIsIGRpZ2l0cz0yKQojJyBBcyBpdCBzZWVtcyB3ZSBjb3VsZCBzdGlsbCBpbXByb3ZlIGJ5IGFkZGluZyBtb3JlIHN0cnVjdHVyZSBhbmQKIycgdGltZSB2YXJ5aW5nIHNlYXNvbmFsIGVmZmVjdCwgaXQgc2VlbXMgdGhlIHZhcmlhYmlsaXR5IGluIHRoZQojJyBudW1iZXIgb2YgYmlydGhzIGZyb20gZGF5IHRvIGRheSBpcyBxdWl0ZSB3ZWxsIHByZWRpY3RhYmxlLiBPZgojJyBjb3Vyc2UgYmlnIHBhcnQgb2YgdGhlIHZhcmlhdGlvbiBpcyBkdWUgdG8gcGxhbm5lZCBpbmR1Y2VkIGJpcnRocwojJyBhbmQgYy1zZWN0aW9ucywgYW5kIHRodXMgaG9zcGl0YWxzIGRvIGFscmVhZHkgY29udHJvbCB0aGUgbnVtYmVyIG9mCiMnIGJpcnRocyBwZXIgZGF5IGFuZCB0aGVyZSBpcyBubyByZWFsbHkgcHJhY3RpY2FsIHVzZSBmb3IgdGhlCiMnIHJlc3VsdC4gSG93ZXZlciB0aGVyZSBhcmUgcGxlbnR5IG9mIHNpbWlsYXIgdGltZSBzZXJpZXMsIGZvcgojJyBleGFtcGxlLCBpbiBjb25zdW1lciBiZWhhdmlvciB0aGF0IGFyZSBhZmZlY3RlZCBieSBzcGVjaWFsIGRheXMuCiMnCiMnICMjIyBNb3JlIGFjY3VyYXRlIGluZmVyZW5jZQojJyAKIycgRHVyaW5nIGFsbCB0aGUgaXRlcmF0aXZlIG1vZGVsIGJ1aWxkaW5nIHdlIGZhdm9yZWQgb3B0aW1pemF0aW9uIGFuZAojJyBzaG9ydCBNQ01DIGNoYWlucy4gSW4gdGhlIGVuZCB3ZSBhbHNvIHJ1biB3aXRoIGhpZ2hlciBhZGFwdF9kZWx0YQojJyB0byByZWR1Y2UgdGhlIHByb2JhYmlsaXR5IG9mIGRpdmVyZ2VuY2VzLCBoaWdoZXIgbWF4aW11bSB0cmVlZGVwdGgKIycgdG8gZW5zdXJlIGhpZ2hlciBlZmZlY3RpdmUgc2FtcGxlIHNpemUgcGVyIGl0ZXJhdGlvbiAoRVNTIHBlcgojJyBzZWNvbmQgZG9lc24ndCBuZWNlc3NhcmlseSBpbXByb3ZlKSwgYW5kIHJ1biBtdWNoIGxvbmdlciBjaGFpbnMsCiMnIGJ1dCBkaWRuJ3Qgc2VlIHByYWN0aWNhbCBkaWZmZXJlbmNlcyBpbiBwbG90cyBvciBMT08tQ1YgdmFsdWVzLiBBcwojJyBydW5uaW5nIHRoZXNlIGxvbmdlciBjaGFpbnMgY2FuIHRha2UgaG91cnMgdGhleSBhcmUgbm90IHJ1biBhcyBwYXJ0CiMnIG9mIHRoaXMgbm90ZWJvb2suIEFuIGV4YW1wbGUgb2YgaG93IHRvIHJlZHVjZSBwcm9iYWJpbGl0eSBvZgojJyBkaXZlcmdlbmNlcyBhbmQgaW5jcmVhc2UgbWF4aW11bSB0cmVlZGVwdGggaXMgc2hvd24gYmVsb3cgKHRoZXJlIGlzCiMnIHJhcmVseSBuZWVkIHRvIGluY3JlYXNlIGFkYXB0X2RlbHRhIGxhcmdlciB0aGFuIDAuOTUgYW5kIGlmIHRoZXJlCiMnIGFyZSBzdGlsbCBkaXZlcmdlbmNlcyB3aXRoIGFkYXB0X2RlbHRhIGVxdWFsIHRvIDAuOTksIHRoZSBwb3N0ZXJpb3IKIycgaGFzIHNlcmlvdXMgcHJvYmxlbXMgYW5kIGl0IHNob3VsZCBiZSBjb25zaWRlcmVkIHdoZXRoZXIKIycgcmUtcGFyYW1ldGVyaXphdGlvbiwgYmV0dGVyIGRhdGEgb3IgbW9yZSBpbmZvcm1hdGl2ZSBwcmlvcnMgY291bGQKIycgaGVscCkuCiMjIGZpdDh0bnUgPC0gbW9kZWw4dG51JHNhbXBsZShkYXRhPXN0YW5kYXRhOCwgY2hhaW5zPTQsIHBhcmFsbGVsX2NoYWlucz00LAojIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWRhcHRfZGVsdGE9MC45NSwgbWF4X3RyZWVkZXB0aD0xNSkK
IycgLS0tCiMnIHRpdGxlOiAiQmF5ZXNpYW4gd29ya2Zsb3cgYm9vayAtIEJpcnRoZGF5cyIKIycgYXV0aG9yOiAiR2VsbWFuLCBWZWh0YXJpLCBTaW1wc29uLCBldCBhbCIKIycgZGF0ZTogIkZpcnN0IHZlcnNpb24gMjAyMC0xMi0yOC4gTGFzdCBtb2RpZmllZCBgciBmb3JtYXQoU3lzLkRhdGUoKSlgLiIKIycgb3V0cHV0OgojJyAgIGh0bWxfZG9jdW1lbnQ6CiMnICAgICB0aGVtZTogcmVhZGFibGUKIycgICAgIHRvYzogdHJ1ZQojJyAgICAgdG9jX2RlcHRoOiAzCiMnICAgICB0b2NfZmxvYXQ6IHRydWUKIycgICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKIycgLS0tCgojJyBXb3JrZmxvdyBmb3IgaXRlcmF0aXZlIGJ1aWxkaW5nIG9mIGEgdGltZSBzZXJpZXMgbW9kZWwuCiMnCiMnIFdlIGFuYWx5c2UgdGhlIHJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgcGVyIGRheSBpbiBVU0EgMTk2OS0xOTg4CiMnIHVzaW5nIEdhdXNzaWFuIHByb2Nlc3MgdGltZSBzZXJpZXMgbW9kZWwgd2l0aCBzZXZlcmFsIG1vZGVsCiMnIGNvbXBvbmVudHMgdGhhdCBjYW4gZXhwbGFpbiB0aGUgbG9uZyB0ZXJtLCBzZWFzb25hbCwgd2Vla2x5LCBkYXkgb2YKIycgeWVhciwgYW5kIHNwZWNpYWwgZmxvYXRpbmQgZGF5IHZhcmlhdGlvbi4KIycKIycgU3RhbiBtb2RlbCBjb2RlcyBhcmUgYXZhaWxhYmxlIGluIFt0aGUgY29ycmVzcG9uZGluZyBnaXQgcmVwb10oaHR0cHM6Ly9naXRodWIuY29tL2F2ZWh0YXJpL2Nhc2VzdHVkaWVzL3RyZWUvbWFzdGVyL0JpcnRoZGF5cykKIycKIycgLS0tLS0tLS0tLS0tLQojJyAKCiMrIHNldHVwLCBpbmNsdWRlPUZBTFNFCmtuaXRyOjpvcHRzX2NodW5rJHNldChtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRSwgd2FybmluZz1GQUxTRSwgY29tbWVudD1OQSwgY2FjaGU9RkFMU0UpCiMgc3dpdGNoIHRoaXMgdG8gVFJVRSB0byBzYXZlIGZpZ3VyZXMgaW4gc2VwYXJhdGUgZmlsZXMKc2F2ZWZpZ3MgPC0gRkFMU0UKCiMnICMjIyMgTG9hZCBwYWNrYWdlcwpsaWJyYXJ5KCJycHJvanJvb3QiKQpyb290PC1oYXNfZmlsZSgiLldvcmtmbG93LUV4YW1wbGVzLXJvb3QiKSRtYWtlX2ZpeF9maWxlKCkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoY21kc3RhbnIpCmxpYnJhcnkocG9zdGVyaW9yKQpvcHRpb25zKHBpbGxhci5uZWcgPSBGQUxTRSwgcGlsbGFyLnN1YnRsZT1GQUxTRSwgcGlsbGFyLnNpZ2ZpZz0yKQpsaWJyYXJ5KGxvbykKbGlicmFyeShiYXllc3Bsb3QpCnRoZW1lX3NldChiYXllc3Bsb3Q6OnRoZW1lX2RlZmF1bHQoYmFzZV9mYW1pbHkgPSAic2FucyIpKQpsaWJyYXJ5KHBhdGNod29yaykKc2V0MSA8LSBSQ29sb3JCcmV3ZXI6OmJyZXdlci5wYWwoNywgIlNldDEiKQoKIycgIyMgTG9hZCBhbmQgcGxvdCBkYXRhCiMnIAojJyBMb2FkIGJpcnRoZGF5cyBwZXIgZGF5IGluIFVTQSAxOTY5LTE5ODg6CmRhdGEgPC0gcmVhZF9jc3Yocm9vdCgiQmlydGhkYXlzL2RhdGEiLCAiYmlydGhzX3VzYV8xOTY5LmNzdiIpKQoKIycgQWRkIGRhdGUgdHlwZSBjb2x1bW4gZm9yIHBsb3R0aW5nCmRhdGEgPC0gZGF0YSAlPiUKICBtdXRhdGUoZGF0ZSA9IGFzLkRhdGUoIjE5NjgtMTItMzEiKSArIGlkLAogICAgICAgICBiaXJ0aHNfcmVsYXRpdmUxMDAgPSBiaXJ0aHMvbWVhbihiaXJ0aHMpKjEwMCkKCiMnICMjIyBQbG90IGFsbCBiaXJ0aHMKIycKIycgV2UgY2FuIHNlZSBzbG93IHZhcmlhdGlvbiBpbiB0cmVuZCwgeWVhcmx5IHBhdHRlcm4sIGFuZCBlc3BlY2lhbGx5CiMnIGluIHRoZSBsYXRlciB5ZWFycyBzcHJlYWQgdG8gbG93ZXIgYW5kIGhpZ2hlciB2YWx1ZXMuCmRhdGEgJT4lCiAgZ2dwbG90KGFlcyh4PWRhdGUsIHk9YmlydGhzKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0pICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIikKCiMnICMjIyBQbG90IGFsbCBiaXJ0aHMgYXMgcmVsYXRpdmUgdG8gbWVhbgojJwojJyBUbyBtYWtlIHRoZSBpbnRlcnByZXRhdGlvbiB3ZSBzd2l0Y2ggdG8gZXhhbWluZSB0aGUgcmVsYXRpdmUKIycgY2hhbmdlLCB3aXRoIHRoZSBtZWFuIGxldmVsIGRlbm90ZWQgd2l0aCAxMDAuCmRhdGEgJT4lCiAgZ2dwbG90KGFlcyh4PWRhdGUsIHk9YmlydGhzX3JlbGF0aXZlMTAwKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBiaXJ0aHMgcGVyIGRheSIpCgojJyAjIyMgUGxvdCBtZWFuIHBlciBkYXkgb2YgeWVhcgojJwojJyBXZSBjYW4gc2VlIHRoZSBnZW5lcmljIHBhdHRlcm4gaW4geWVhcmx5IHNlYXNvbmFsIHRyZW5kIHNpbXBseSBieQojJyBhdmVyYWdpbmcgb3ZlciBlYWNoIGRheSBvZiB5ZWFyIChkYXlfb2ZfeWVhciBoYXMgbnVtYmVycyBmcm9tIDEgdG8KIycgMzY2IGV2ZXJ5IHllYXIgd2l0aCBsZWFwIGRheSBiZWluZyA2MCBhbmQgMXN0IE1hcmNoIDYxIGFsc28gb24KIycgbm9uLWxlYXAteWVhcnMpLgpkYXRhICU+JQogIGdyb3VwX2J5KGRheV9vZl95ZWFyMikgJT4lCiAgc3VtbWFyaXNlKG1lYW5iaXJ0aHM9bWVhbihiaXJ0aHNfcmVsYXRpdmUxMDApKSAlPiUKICBnZ3Bsb3QoYWVzKHg9YXMuRGF0ZSgiMTk4Ni0xMi0zMSIpK2RheV9vZl95ZWFyMiwgeT1tZWFuYmlydGhzKSkgKwogIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKSArCiAgbGFicyh4PSJEYXkgb2YgeWVhciIsIHk9IlJlbGF0aXZlIGJpcnRocyBwZXIgZGF5IG9mIHllYXIiKQoKIycgIyMjIFBsb3QgbWVhbiBwZXIgZGF5IG9mIHdlZWsKIycgCiMnIFdlIGNhbiBzZWUgdGhlIGdlbmVyaWMgcGF0dGVybiBpbiB3ZWVrbHkgdHJlbmQgc2ltcGx5IGJ5IGF2ZXJhZ2luZwojJyBvdmVyIGVhY2ggZGF5IG9mIHdlZWsuCmRhdGEgJT4lCiAgZ3JvdXBfYnkoZGF5X29mX3dlZWspICU+JQogIHN1bW1hcmlzZShtZWFuYmlydGhzPW1lYW4oYmlydGhzX3JlbGF0aXZlMTAwKSkgJT4lCiAgZ2dwbG90KGFlcyh4PWRheV9vZl93ZWVrLCB5PW1lYW5iaXJ0aHMpKSArCiAgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBzaXplPTQpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gMTo3LCBsYWJlbHM9YygnTW9uJywnVHVlJywnV2VkJywnVGh1JywnRnJpJywnU2F0JywnU3VuJykpICsKICBsYWJzKHg9IkRheSBvZiB3ZWVrIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyBvZiB3ZWVrIikKCiMnICMjIFByZXZpb3VzIGFuYWx5c2VzCiMnIAojJyBXZSBoYXZlIGFuYWx5c2VkIHRoZSBzYW1lIGRhdGEgYmVmb3JlIGluIEJEQTMgYW5kIHRodXMgaGFkIGlkZWEgb2YKIycgd2hhdCBraW5kIG9mIG1vZGVsIHRvIHVzZS4gRm9yIEJEQTMgd2UgdXNlZCBHUHN0dWZmIHNvZnR3YXJlIHdoaWNoCiMnIGlzIEdhdXNzaWFuIHByb2Nlc3Mgc3BlY2lmaWMgc29mdHdhcmUgZm9yIE1hdGxhYiBhbmQgT2N0YXZlLiBBcwojJyBTdGFuIGhhcyBhaW1lZCB0byBiZSB2ZXJ5IGdlbmVyaWMgaXQgY2FuIGJlIHNsb3dlciB0aGFuIHNwZWNpYWxpemVkCiMnIHNvZnR3YXJlIGZvciBzb21lIHNwZWNpZmljIG1vZGVscyBzdWNoIGFzIEdhdXNzaWFuIHByb2Nlc3NlcywgYnV0CiMnIFN0YW4gcHJvdmlkZXMgbW9yZSBmbGV4aWJpbGl0eSBpbiB0aGUgbW9kZWwgZGVmaW5pdGlvbi4KIycKIycgUml1dG9ydC1NYXlvbCBldCBhbCAoMjAyMCkgZGVtb25zdHJhdGUgSGlsYmVydCBzcGFjZSBhcHByb3hpbWF0ZQojJyBiYXNpcyBmdW5jdGlvbiBhcHByb3hpbWF0aW9uIG9mIEdhdXNzaWFuIHByb2Nlc3NlcyBhbHNvIGZvciB0aGUKIycgc2FtZSBiaXJ0aGRheSBkYXRhLiBJbiB0aGUgZXhwZXJpbWVudHMgdGhlIGluZmVyZW5jZSB3YXMgc2xvd2VyCiMnIHRoYW4gZXhwZWN0ZWQgcmFpc2luZyBzdXNwaWNpb24gb2YgaW5lZmZpY2llbnQgbW9kZWwgY29kZSBvciBiYWQKIycgcG9zdGVyaW9yIHNoYXBlIGR1ZSB0byBiYWQgbW9kZWwgc3BlY2lmaWNhdGlvbi4KIycKIycgIyMgV29ya2Zsb3cgZm9yIHF1aWNrIGl0ZXJhdGl2ZSBtb2RlbCBidWlsZGluZwojJwojJyBFdmVuIHdlIGhhdmUgZ2VuZXJhbCBpZGVhIGZvciB0aGUgbW9kZWwgKHNsb3cgdHJlbmQsIHNlYXNvbmFsCiMnIHRyZW5kLCB3ZWVrZGF5IGVmZmVjdCwgZXRjKSwgYWRkaW5nIHRoZW0gYWxsIGF0IG9uY2UgdG8gdGhlIG1vZGVsCiMnIG1ha2VzIHRoZSBtb2RlbCBjb21wbGV4IGFuZCBkaWZmaWN1bHQgdG8gZGVidWcgYW5kIHNvbHZlIHRoZQojJyBjb21wdXRhdGlvbmFsIHByb2JsZW1zLiBJdCBpcyB0aHVzIG5hdHVyYWwgdG8gYnVpbGQgdGhlIG1vZGVsCiMnIGdyYWR1YWxseSBhbmQgY2hlY2sgdGhhdCBlYWNoIGFkZGl0aW9uIHdvcmtzIGJlZm9yZSBhZGRpbmcgdGhlIG5leHQKIycgbW9kZWwgY29tcG9uZW50LiBEdXJpbmcgdGhpcyBpdGVyYXRpdmUgbW9kZWwgYnVpbGRpbmcgd2Ugd2FudCB0aGUKIycgaW5mZXJlbmNlIHRvIGJlIGZhc3QsIGJ1dCBpdCBkb2Vzbid0IG5lZWQgdG8gYmUgdmVyeSBhY2N1cmF0ZSBhcwojJyBsb25nIGFzIHF1YWxpdGF0aXZlbHkgdGhlIG5ldyBtb2RlbCBpcyByZWFzb25hYmxlLiBGb3IgcXVpY2sKIycgdGVzdGluZyBhbmQgaXRlcmF0aXZlIG1vZGVsIGJ1aWxkaW5nIHdlIGNhbiB1c2Ugb3B0aW1pemF0aW9uIGFuZAojJyBzaG9ydGVyIE1DTUMgY2hhaW5zIHRoYXQgd2Ugd291bGQgbm90IHJlY29tbWVuZCBmb3IgdGhlIGZpbmFsCiMnIGluZmVyZW5jZS4gIEZ1cnRoZXJtb3JlLCBpbiB0aGlzIHNwZWNpZmljIGV4YW1wbGUsIHRoZSBuZXcKIycgYWRkaXRpb25zIGFyZSBxdWFsaXRhdGl2ZWx5IHNvIGNsZWFyIGltcHJvdmVtZW50cyB0aGF0IHRoZXJlIGlzIG5vCiMnIG5lZWQgZm9yIHF1YW50aXRhdGl2ZSBtb2RlbCBjb21wYXJpc29uIHdoZXRoZXIgdGhlIGFkZGl0aW9ucyBhcmUKIycgYGBzaWduaWZpY2FudCcnIChzZWUgYWxzbyBOYXZhcnJvLCAyMDE5KSBhbmQgdGhlcmUgaXMgbm8gZGFuZ2VyIG9mCiMnIG92ZXJmaXR0aW5nLiBBbHRob3VnaCB0aGVyZSBpcyBvbmUgcGFydCBvZiB0aGUgbW9kZWwgd2hlcmUgdGhlIGRhdGEKIycgaXMgd2Vha2x5IGluZm9ybWF0aXZlIGFuZCB0aGUgcHJpb3IgY2hvaWNlcyBzZWVtIHRvIG1hdHRlciBhbmQKIycgd2UnbGwgZ2V0IGJhY2sgdG8gdGhpcyBhbmQgY29uc2VxdWVuY2VzIGxhdGVyLiBPdmVyYWxsIHdlIGJ1aWxkCiMnIHRlbnMgb2YgZGlmZmVyZW50IG1vZGVscyBidXQgaWxsdXN0cmF0ZSBoZXJlIG9ubHkgdGhlIG1haW4gbGluZS4KIycgCgojJyAjIyBNb2RlbHMgZm9yIHJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aGRheXMKIycKIycgQXMgdGhlIHJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgaXMgcG9zaXRpdmUgaXQncyBuYXR1cmFsIHRvIG1vZGVsCiMnIHRoZSBsb2dhcml0aG0gdmFsdWUuIFRoZSBnZW5lcmljIGZvcm0gb2YgdGhlIG1vZGVscyBpcwojJyAkJAojJyB5IFxzaW0gXG1ib3h7bm9ybWFsfShmKHgpLCBcc2lnbWEpLAojJyAkJAojJyB3aGVyZSAkZiQgaXMgZGlmZmVyZW50IGFuZCBncmFkdWFsbHkgbW9yZSBjb21wbGV4IGZ1bmN0aW9uCiMnIGNvbmRpdGlvbmFsIG9uICR4JCB0aGF0IGluY2x1ZGVzIHJ1bm5pbmcgZGF5IG51bWJlciwgZGF5IG9mIHllYXIsCiMnIGRheSBvZiB3ZWVrIGFuZCBldmVudHVhbGx5IHNvbWUgc3BlY2lhbCBmbG9hdGluZyBVUyBiYW5rIGhvbGlkYXlzLgojJwojJyAjIyMgTW9kZWwgMTogU2xvdyB0cmVuZAojJwojJyBUaGUgbW9kZWwgMSBpcyBqdXN0IHRoZSBzbG93IHRyZW5kIG92ZXIgdGhlIHllYXJzIHVzaW5nIEhpbGJlcnQKIycgc3BhY2UgYmFzaXMgZnVuY3Rpb24gYXBwcm94aW1hdGVkIEdhdXNzaWFuIHByb2Nlc3MKIycgJCQKIycgZiA9IFxtYm94e2ludGVyY2VwdH0gKyBmXzFcXAojJyBcbWJveHtpbnRlcmNlcHR9IFxzaW0gXG1ib3h7bm9ybWFsfSgwLDEpXFwKIycgZl8xIFxzaW0gXG1ib3h7R1B9KDAsS18xKQojJyAkJAojJyB3aGVyZSBHUCBoYXMgZXhwb25lbnRpYXRlZCBxdWFkcmF0aWMgY292YXJpYW5jZSBmdW5jdGlvbi4KIycgCiMnIEluIHRoaXMgcGhhc2UgdGhlIGNvZGUgZnJvbSBSaXV0b3J0LU1heW9sIGV0IGFsLigyMDIwKSB3YXMgY2xlYW5lZAojJyBhbmQgd3JpdHRlbiB0byBiZSBtb3JlIGVmZmljaWVudCwgYnV0IG9ubHkgdGhlIG9uZSBHUCBjb21wb25lbnQgd2FzCiMnIGluY2x1ZGVkIHRvIG1ha2UgdGhlIHRlc3RpbmcgZWFzaWVyLiBBbHRob3VnaCB0aGUgY29kZSB3YXMgbWFkZQojJyBtb3JlIGVmZmljaWVudCwgdGhlIGFpbSB3YXNuJ3QgdG8gbWFrZSBpdCB0aGUgZmFzdGVzdCBwb3NzaWJsZSBhcwojJyB0aGUgbGF0ZXIgbW9kZWwgY2hhbmdlcyBtYXkgaGF2ZSBiaWdnZXIgZWZmZWN0IG9uIHRoZSBwZXJmb3JtYW5jZQojJyAoaXQncyBnb29kIG8gYXZvaWQgcHJlbWF0dXJlIG9wdGltaXphdGlvbikuIFdlIGFsc28gdXNlIHF1aXRlIHNtYWxsCiMnIG51bWJlciBvZiBiYXNpcyBmdW5jdGlvbnMgdG8gbWFrZSB0aGUgY29kZSBydW4gZmFzdGVyLCBhbmQgb25seQojJyBsYXRlciBleGFtaW5lIG1vcmUgY2FyZWZ1bGx5IHdoZXRoZXIgdGhlIG51bWJlciBvZiBiYXNpcyBmdW5jdGlvbgojJyBpcyBzdWZmaWNpZW50IGNvbXBhcmVkIHRvIHRoZSBwb3N0ZXJpb3Igb2YgdGhlIGxlbmd0aCBzY2FsZSAoc2VlLAojJyBSaXV0b3J0LU1heW9sIGV0IGFsLiwgMjAyMCkuCiMnCgojJyBDb21waWxlIFN0YW4gbW9kZWwgW2dwYmYxLnN0YW5dKGh0dHBzOi8vZ2l0aHViLmNvbS9hdmVodGFyaS9jYXNlc3R1ZGllcy9ibG9iL21hc3Rlci9CaXJ0aGRheXMvZ3BiZjEuc3Rhbikgd2hpY2ggaW5jbHVkZXMgW2dwYmFzaXNmdW5fZnVuY3Rpb25zMS5zdGFuXShodHRwczovL2dpdGh1Yi5jb20vYXZlaHRhcmkvY2FzZXN0dWRpZXMvYmxvYi9tYXN0ZXIvQmlydGhkYXlzL2dwYmFzaXNmdW5fZnVuY3Rpb25zMS5zdGFuKQojKyBtb2RlbDEsIHJlc3VsdHM9J2hpZGUnCm1vZGVsMSA8LSBjbWRzdGFuX21vZGVsKHN0YW5fZmlsZSA9IHJvb3QoIkJpcnRoZGF5cyIsICJncGJmMS5zdGFuIiksCiAgICAgICAgICAgICAgICAgICAgICAgIGluY2x1ZGVfcGF0aHMgPSByb290KCJCaXJ0aGRheXMiKSkKIycgRGF0YSB0byBiZSBwYXNzZWQgdG8gU3RhbgpzdGFuZGF0YTEgPC0gbGlzdCh4PWRhdGEkaWQsCiAgICAgICAgICAgICAgICAgIHk9bG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSwKICAgICAgICAgICAgICAgICAgTj1sZW5ndGgoZGF0YSRpZCksCiAgICAgICAgICAgICAgICAgIGNfZjE9MS41LCAjIGZhY3RvciBjIG9mIGJhc2lzIGZ1bmN0aW9ucyBmb3IgR1AgZm9yIGYxCiAgICAgICAgICAgICAgICAgIE1fZjE9MTApICAjIG51bWJlciBvZiBiYXNpcyBmdW5jdGlvbnMgZm9yIEdQIGZvciBmMQoKIycgQXMgdGhlIGJhc2lzIGZ1bmN0aW9uIGFwcHJveGltYXRpb24gYW5kIHByaW9ycyByZXN0cmljdCB0aGUKIycgY29tcGxleGl0eSBvZiBHUCwgd2UgY2FuIHNhZmVseSB1c2Ugb3B0aW1pemF0aW9uIHRvIGdldCBhIHZlcnkKIycgcXVpY2sgaW5pdGlhbCByZXN1bHQgdG8gY2hlY2sgdGhhdCB0aGUgbW9kZWwgY29kZSBpcyBjb21wdXRpbmcgd2hhdAojJyB3ZSBpbnRlbmRlZC4gQXMgdGhlcmUgYXJlIG9ubHkgMTQgcGFyYW1ldGVycyBhbmQgNzMwNSBvYnNlcnZhdGlvbnMKIycgaXQncyBsaWtlbHkgdGhhdCB0aGUgcG9zdGVyaW9yIGlzIGNsb3NlIHRvIG5vcm1hbCAoaW4gdW5jb25zdHJhaW5lZAojJyBzcGFjZSkuIEluIHRoaXMgY2FzZSB0aGUgb3B0aW1pemF0aW9uIHRha2VzIGxlc3MgdGhhbiBvbmUgc2Vjb25kCiMnIHdoaWxlIE1DTUMgc2FtcGxpbmcgd2l0aCBkZWZhdWx0IG9wdGlvbnMgd291bGQgaGF2ZSB0YWtlbiBzZXZlcmFsCiMnIG1pbnV0ZXMuIEFsdGhvdWdoIHRoaXMgcmVzdWx0IGNhbiBiZSB1c2VmdWwgaW4gYSBxdWljayB3b3JrZmxvdywKIycgdGhlIHJlc3VsdCBzaG91bGQgbm90IGJlIHVzZWQgYXMgdGhlIGZpbmFsIHJlc3VsdC4KIysgb3B0MSwgcmVzdWx0cz0naGlkZScKb3B0MSA8LSBtb2RlbDEkb3B0aW1pemUoZGF0YSA9IHN0YW5kYXRhMSwgaW5pdD0wLCBhbGdvcml0aG09J2JmZ3MnKQojJyBDaGVjayB3aGV0aGVyIHBhcmFtZXRlcnMgaGF2ZSByZWFzb25hYmxlIHZhbHVlcwpvZHJhd3MxIDwtIG9wdDEkZHJhd3MoKQpzdWJzZXQob2RyYXdzMSwgdmFyaWFibGU9YygnaW50ZXJjZXB0Jywnc2lnbWFfZjEnLCdsZW5ndGhzY2FsZV9mMScsJ3NpZ21hJykpCgojJyBDb21wYXJlIHRoZSBtb2RlbCB0byB0aGUgZGF0YQpvRWYgPC0gZXhwKGFzLm51bWVyaWMoc3Vic2V0KG9kcmF3czEsIHZhcmlhYmxlPSdmJykpKQpkYXRhICU+JQogIG11dGF0ZShvRWYgPSBvRWYpICU+JQogIGdncGxvdChhZXMoeD1kYXRlLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsKICBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIGdlb21fbGluZShhZXMoeT1vRWYpLCBjb2xvcj1zZXQxWzFdKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyIpCgojJyBBZnRlciB3ZSBnZXQgdGhlIG1vZGVsIHdvcmtpbmcgdXNpbmcgb3B0aW1pemF0aW9uIHdlIGNhbiBjb21wYXJlCiMnIHRoZSByZXN1bHQgdG8gdXNpbmcgc2hvcnQgTUNNQyBjaGFpbnMgd2hpY2ggd2lsbCBhbHNvIHByb3ZpZGUgdXMKIycgYWRkaXRpb25hbCBpbmZvcm1hdGlvbiBvbiBzcGVlZCBvZiBkaWZmZXJlbnQgY29kZSBpbXBsZW1lbnRhdGlvbnMKIycgZm9yIHRoZSBzYW1lIG1vZGVsLiBXZSBpbnRlbnRpb25hbGx5IHVzZSBqdXN0IDEvMTB0aCBsZW5ndGggZnJvbQojJyB0aGUgdXN1YWwgcmVjb21tZW5kYXRpb24sIGFzIGR1cmluZyB0aGUgaXRlcmF0aXZlIG1vZGVsIGJ1aWxkaW5nIGEKIycgcm91Z2ggcmVzdWx0cyBhcmUgc3VmZmljaWVudC4gV2hlbiB0ZXN0aW5nIHRoZSBjb2RlIHdlIGluaXRpYWxseQojJyB1c2VkIGp1c3Qgb25lIGNoYWluLCBidXQgYXQgdGhpcyBwb2ludCBydW5uaW5nIGZvdXIgY2hhaW5zIHdpdGgKIycgZm91ciBjb3JlIENQVSBkb2Vzbid0IGFkZCBtdWNoIHRvIHRoZSB3YWxsIGNsb2NrIHRpbWUsIGJ1dCBnaXZlcwojJyBtb3JlIGluZm9ybWF0aW9uIG9mIGhvdyBlYXN5IGl0IGlzIHNhbXBsZSBmcm9tIHRoZSBwb3N0ZXJpb3IgYW5kCiMnIGNhbiByZXZlYWwgaWYgdGhlcmUgYXJlIG11bHRpcGxlIG1vZGVzLiBBbHRob3VnaCB0aGUgcmVzdWx0IGZyb20KIycgc2hvcnQgY2hhaW5zIGNhbiBiZSB1c2VmdWwgaW4gYSBxdWljayB3b3JrZmxvdywgdGhlIHJlc3VsdCBzaG91bGQKIycgbm90IGJlIHVzZWQgYXMgdGggZmluYWwgcmVzdWx0LgojKyBmaXQxLCByZXN1bHRzPSdoaWRlJwpmaXQxIDwtIG1vZGVsMSRzYW1wbGUoZGF0YT1zdGFuZGF0YTEsIGl0ZXJfd2FybXVwPTEwMCwgaXRlcl9zYW1wbGluZz0xMDAsCiAgICAgICAgICAgICAgICAgICAgICBjaGFpbnM9NCwgcGFyYWxsZWxfY2hhaW5zPTQsIHNlZWQ9Mzg5MSkKCiMnIERlcGVuZGluZyBvbiB0aGUgcmFuZG9tIHNlZWQgYW5kIGx1Y2ssIHdlIHNvbWV0aW1lcyBvYnNlcnZlZCB0aGF0CiMnIHNvbWUgb2YgdGhlIGNoYWlucyBnb3Qgc3R1Y2sgaW4gZGlmZmVyZW50IG1vZGVzLiBXZSBjb3VsZCBzZWUgdGhpcwojJyBpbiBoaWdoIFJoYXQgYW5kIGxvdyBFU1MgZGlhZ25vc3RpYyB2YWx1ZXMuCmRyYXdzMSA8LSBmaXQxJGRyYXdzKCkKc3VtbWFyaXNlX2RyYXdzKHN1YnNldChkcmF3czEsIHZhcmlhYmxlPWMoJ2ludGVyY2VwdCcsJ3NpZ21hX2YxJywnbGVuZ3Roc2NhbGVfZjEnLCdzaWdtYScpKSkKIycgRXhhbWluaW5nIHRoZSB0cmFjZSBwbG90cyBzaG93cyB0aGUgbXVsdGltb2RhbGl0eSBjbGVhcmx5LgptY21jX3RyYWNlKGRyYXdzMSwgcmVnZXhfcGFycz1jKCdpbnRlcmNlcHQnLCdzaWdtYV9mMScsJ2xlbmd0aHNjYWxlX2YxJywnc2lnbWEnKSkKCiMnIEluIHRoaXMgY2FzZSBpdCB3YXMgZWFzeSB0byBmaWd1cmUgb3V0IHRoYXQgc29tZSBvZiB0aGUgY2hhaW5zIGdvdAojJyBzdHVjayBpbiBxdWFsaXRhdGl2ZWx5IG11Y2ggd29yc2UgbW9kZXMuIFdlIGRvbid0IGluIGdlbmVyYWwKIycgcmVjb21tZW5kIHRvIHN0YXJ0IGZyb20gdGhlIG1vZGUgYXMgdGhlIG1vZGUgaXMgbm90IHVzdWFsbHkKIycgcmVwcmVzZW50YXRpdmUgcG9pbnQgaW4gaGllcmFyY2hpY2FsIG1vZGVsIHBvc3RlcmlvciBvciBpbiBoaWdoCiMnIGRpbWVuc2lvbmFsIHBvc3RlcmlvciwgYnV0IHdlIGNhbiB1c2UgdGhpcyBhZ2FpbiB0byBzcGVlZCB1cCB0aGUKIycgaXRlcmF0aXZlIG1vZGVsIGJ1aWxkaW5nIGFzIGxvbmcgYXMgd2UgY2hlY2sgdGhhdCB0aGUgb3B0aW1pemF0aW9uCiMnIHJlc3VsdCBpcyBzZW5zaWJsZSBhbmQgbGF0ZXIgZG8gbW9yZSBjYXJlZnVsIGluZmVyZW5jZS4gQWx0aG91Z2gKIycgdGhlIHJlc3VsdCBmcm9tIHNob3J0IGNoYWlucyBjYW4gYmUgdXNlZnVsIGluIGEgcXVpY2sgd29ya2Zsb3csIHRoZQojJyByZXN1bHQgc2hvdWxkIG5vdCBiZSB1c2VkIGFzIHRoZSBmaW5hbCByZXN1bHQuCmluaXQxIDwtIHNhcHBseShjKCdpbnRlcmNlcHQnLCdzaWdtYV9mMScsJ2xlbmd0aHNjYWxlX2YxJywnYmV0YV9mMScsJ3NpZ21hJyksCiAgICAgICAgICAgICAgICBmdW5jdGlvbih2YXJpYWJsZSkge2FzLm51bWVyaWMoc3Vic2V0KG9kcmF3czEsIHZhcmlhYmxlPXZhcmlhYmxlKSl9KQojKyBmaXQxaW5pdCwgcmVzdWx0cz0naGlkZScKZml0MSA8LSBtb2RlbDEkc2FtcGxlKGRhdGE9c3RhbmRhdGExLCBpdGVyX3dhcm11cD0xMDAsIGl0ZXJfc2FtcGxpbmc9MTAwLAogICAgICAgICAgICAgICAgICAgICAgY2hhaW5zPTQsIHBhcmFsbGVsX2NoYWlucz00LAogICAgICAgICAgICAgICAgICAgICAgaW5pdD1mdW5jdGlvbigpIHsgaW5pdDEgfSkKCiMnIFdlIG5vdyBvYnNlcnZlIGJldHRlciBSaGF0IGFuZCBFU1MgZGlhZ25vc3RpYyB2YWx1ZXMsIGFsdGhvdWdoIGR1ZQojJyB0byB2ZXJ5IHNob3J0IGNoYWlucyB0aGV5IGFyZSBub3QgeWV0IHBlcmZlY3QuIFdlIGFyZSBsaWtlbHkgdG8KIycgYWxzbyBvYnNlcnZlIEhhbWlsdG9uaWFuIE1vbnRlIENhcmxvIGRpdmVyZ2VuY2VzIGFuZCB0cmVlZGVwdGgKIycgZXhjZWVkZW5jZXMgaW4gZHluYW1pYyBidWlsZGluZyBvZiB0aGUgSGFtaWx0b25pYW4gdHJhamVjdG9yeSwKIycgYnV0IHRoZXJlIGlzIG5vIG5lZWQgdG8gd29ycnkgYWJvdXQgdGhvc2UgYXMgbG9uZyBhcyB0aGUKIycgbW9kZWwgcmVzdWx0cyBhcmUgcXVhbGl0YXRpdmVseSBzZW5zaWJsZSBhcyB0aGVzZSBjb21wdXRhdGlvbmFsCiMnIGlzc3VlcyBjYW4gYWxzbyBnbyBhd2F5IHdoZW4gdGhlIG1vZGVsIGl0c2VsZiBpcyBpbXByb3ZlZC4gSW4gYWxsCiMnIHRoZSBmb2xsb3dpbmcgc2hvcnQgTUNNQyBzYW1wbGluZ3Mgd2UgZ2V0IHNvbWUgb3IgbWFueSBkaXZlcmdlbmNlcwojJyBhbmQgdXN1YWxseSB2ZXJ5IGxhcmdlIG51bWJlciBvZiB0cmVlZGVwdGggZXhjZWVkZW5jZXMuIERpdmVyZ2VuY2VzCiMnIGluZGljYXRlIHBvc3NpYmxlIGJpYXMgYW5kIHNob3VsZCBiZSBldmVudHVhbGx5IGludmVzdGlnYXRlZAojJyBjYXJlZnVsbHkuIFRyZWVkZXB0aCBleGNlZWRlbmNlcyBpbmRpY2F0ZSBzdHJvbmcgcG9zdGVyaW9yCiMnIGRlcGVuZGVuY2llcyBhbmQgc2xvdyBtaXhpbmcgYW5kIHNvbWV0aW1lcyB0aGUgcG9zdGVyaW9yIGNhbiBiZQojJyBtdWNoIGltcHJvdmVkIGJ5IGNoYW5naW5nIHRoZSBwYXJhbWV0ZXJpemF0aW9uIG9yIHByaW9ycywgYnV0IGFzCiMnIHRoZSB0cmVlZGVwdGggZXhjZWVkZW5jZXMgZG9uJ3QgaW5kaWNhdGUgYmlhcyB0aGVyZSBpcyBubyBuZWVkIGZvcgojJyBtb3JlIGNhcmVmdWwgYW5hbHlzaXMgaWYgdGhlIHJlc3VsdGluZyBFU1MgYW5kIE1DU0UgdmFsdWVzIGFyZSBnb29kCiMnIGZvciB0aGUgcHVycG9zZSBpbiBoYW5kLiAgV2UnbGwgY29tZSBiYWNrIGxhdGVyIHRvIG1vcmUgY2FyZWZ1bAojJyBhbmFseXNpcyBvZiB0aGUgZmluYWwgbW9kZWxzLgpkcmF3czEgPC0gZml0MSRkcmF3cygpCnN1bW1hcmlzZV9kcmF3cyhzdWJzZXQoZHJhd3MxLCB2YXJpYWJsZT1jKCdpbnRlcmNlcHQnLCdzaWdtYV9mMScsJ2xlbmd0aHNjYWxlX2YxJywnc2lnbWEnKSkpCiMnIFRyYWNlIHBsb3Qgc2hvd3Mgc2xvdyBtaXhpbmcgYnV0IG5vIG11bHRpbW9kYWxpdHkuCm1jbWNfdHJhY2UoZHJhd3MxLCByZWdleF9wYXJzPWMoJ2ludGVyY2VwdCcsJ3NpZ21hX2YxJywnbGVuZ3Roc2NhbGVfZjEnLCdzaWdtYScpKQoKIycgVGhlIG1vZGVsIHJlc3VsdCBmcm9tIHNob3J0IE1DTUMgY2hhaW5zIGxvb2tzIHZlcnkgc2ltaWxhciB0byB0aGUKIycgb3B0aW1pemF0aW9uIHJlc3VsdC4KZHJhd3MxIDwtIGFzX2RyYXdzX21hdHJpeChkcmF3czEpCkVmIDwtIGV4cChhcHBseShzdWJzZXQoZHJhd3MxLCB2YXJpYWJsZT0nZicpLCAyLCBtZWRpYW4pKQpkYXRhICU+JQogIG11dGF0ZShFZiA9IEVmKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9saW5lKGFlcyh5PUVmKSwgY29sb3I9c2V0MVsxXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMiKQoKIycgSWYgd2UgY29tcGFyZSB0aGUgcmVzdWx0IGZyb20gc2hvcnQgc2FtcGxpbmcgdG8gb3B0aW1pemluZywgd2UKIycgZG9uJ3Qgc2VlIHByYWN0aWNhbCBkaWZmZXJlbmNlIGluIHRoZSBwcmVkaWN0aW9ucyAoYWx0aG91Z2ggd2Ugc2VlCiMnIGxhdGVyIG1vcmUgZGlmZmVyZW5jZXMgYmV0d2VlbiBvcHRpbWl6YXRpb24gYW5kIE1DTUMpLgpkYXRhICU+JQogIG11dGF0ZShFZiA9IEVmLAogICAgICAgICBvRWYgPSBvRWYpICU+JQogIGdncGxvdChhZXMoeD1FZiwgeT1vRWYpKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSkgKwogIGdlb21fYWJsaW5lKCkgKwogIGxhYnMoeD0iRWYgZnJvbSBzaG9ydCBNYXJrb3YgY2hhaW4iLCB5PSJFZiBmcm9tIG9wdGltaXppbmciKQoKIycgVGhlIG9yaWdpbmFsIG5vdGVib29rIGNvbnRpbnVlZCB1c2luZyB0aGUKIycgW2dwYmFzaXNmdW5fZnVuY3Rpb25zMS5zdGFuXShodHRwczovL2dpdGh1Yi5jb20vYXZlaHRhcmkvY2FzZXN0dWRpZXMvYmxvYi9tYXN0ZXIvQmlydGhkYXlzL2dwYmFzaXNmdW5fZnVuY3Rpb25zMS5zdGFuKQojJyB1c2VkIGFib3ZlLiBNdWNoIGxhdGVyIFtOaWtvbGFzIFNpY2NoYSBleGFtaW5lZCBtb3JlIGNhcmVmdWxseSB0aGUKIycgcG9zdGVyaW9yIGNvcnJlbGF0aW9uc10oaHR0cHM6Ly9naXRodWIuY29tL25zaWNjaGEvYmlydGhkYXkpIGFuZAojJyBub3RpY2VkIHN0cm9uZyBjb3JyZWxhdGlvbiBiZXR3ZWVuIGludGVyY2VwdCBhbmQgdGhlIGZpcnN0IGJhc2lzCiMnIGZ1bmN0aW9uLiBTdGFuJ3MgZHluYW1pYyBITUMgaXMgc28gZWZmaWNpZW50IHRoYXQgdGhlIGluZmVyZW5jZSBpcwojJyBzdWNjZXNmdWwgYW55d2F5LiBXaGlsZSBOaWtvbGFzIHN1Z2dlc3RlZCByZW1vdmluZyB0aGUgaW50ZXJjZXB0CiMnIHRlcm0sIHRoZSBiZXR0ZXIgc29sdXRpb24gaXMgdG8gbWFrZSB0aGUgYmFzaXMgZnVuY3Rpb25zIHRvIGhhdmUKIycgemVybyBtZWFucy4gV2Ugc2hvdWxkIGhhdmUgbm90aWNlZCB0byBkbyB0aGF0IGFscmVhZHkgZm9yCiMnIFJpdXRvcnQtTWF5b2wgZXQgYWwuLCAoMjAyMCkgcGFwZXIsIGJ1dCBtaXNzZWQgdGhhdC4KIycKIycgRmlsZQojJyBbZ3BiYXNpc2Z1bl9mdW5jdGlvbnMuc3Rhbl0oaHR0cHM6Ly9naXRodWIuY29tL2F2ZWh0YXJpL2Nhc2VzdHVkaWVzL2Jsb2IvbWFzdGVyL0JpcnRoZGF5cy9ncGJhc2lzZnVuX2Z1bmN0aW9ucy5zdGFuKQojJyBoYXMgdGhlIGZpeGVkIGNvZGUgd2hpY2ggbWFrZXMgdGhlIGJhc2lzIGZ1bmN0aW9ucyB0byBoYXZlIHplcm8KIycgbWVhbi4KIycgCgojKyBtb2RlbDFiLCByZXN1bHRzPSdoaWRlJwptb2RlbDFiIDwtIGNtZHN0YW5fbW9kZWwoc3Rhbl9maWxlID0gcm9vdCgiQmlydGhkYXlzIiwgImdwYmYxYi5zdGFuIiksCiAgICAgICAgICAgICAgICAgICAgICAgIGluY2x1ZGVfcGF0aHMgPSByb290KCJCaXJ0aGRheXMiKSkKIysgZml0MWIsIHJlc3VsdHM9J2hpZGUnCmZpdDFiIDwtIG1vZGVsMWIkc2FtcGxlKGRhdGE9c3RhbmRhdGExLCBpdGVyX3dhcm11cD0xMDAsIGl0ZXJfc2FtcGxpbmc9MTAwLAogICAgICAgICAgICAgICAgICAgICAgY2hhaW5zPTQsIHBhcmFsbGVsX2NoYWlucz00LCBzZWVkPTM4OTEpCgojJyBXaXRoIHRoZSBiZXR0ZXIgcG9zdGVyaW9yIGdlb21ldHJ5LCBpdCBpcyB1bmxpa2VseSB0aGF0IHdlIGdldAojJyBzdHVjayBpbiBhIGxvY2FsIG1vZGUgZXZlbiB3aXRoIHRoZSByYW5kb20gaW5pdHMuCmRyYXdzMWIgPC0gZml0MWIkZHJhd3MoKQpzdW1tYXJpc2VfZHJhd3Moc3Vic2V0KGRyYXdzMWIsIHZhcmlhYmxlPWMoJ2ludGVyY2VwdCcsJ3NpZ21hX2YxJywnbGVuZ3Roc2NhbGVfZjEnLCdzaWdtYScpKSkKCiMnIEV4YW1pbmluZyB0aGUgdHJhY2UgcGxvdHMgc2hvd3MgYmV0dGVyIGJlaGF2aW9yLgptY21jX3RyYWNlKGRyYXdzMWIsIHJlZ2V4X3BhcnM9YygnaW50ZXJjZXB0Jywnc2lnbWFfZjEnLCdsZW5ndGhzY2FsZV9mMScsJ3NpZ21hJykpCgojJyBUaGUgcmVtYWluaW5nIG1vZGVscyB1c2UgdGhlIHplcm8gbWVhbiBiYXNpcyBmdW5jdGlvbnMgd2hpY2gKIycgcHJvZHVjZSBiZXR0ZXIgcG9zdGVyaW9yIGdlb21ldHJ5LiAgV2UnbGwgaG93ZXZlciBrZWVwIHVzaW5nIHRoZQojJyBvcHRpbWl6YXRpb24gaW5pdHMgZm9yIHRoZSByZW1haW5pbmcgc2FtcGxpbmdzIHRvIGdldCBzb21lCiMnIHNwZWVkLXVwLgojJyAKCiMnICMjIyBNb2RlbCAyOiBTbG93IHRyZW5kICsgeWVhcmx5IHNlYXNvbmFsIHRyZW5kCiMnIAojJyBUaGUgbW9kZWwgMiBhZGRzIHllYXJseSBzZWFzb25hbCB0cmVuZCB1c2luZyBHUCB3aXRoIHBlcmlvZGljCiMnIGNvdmFyaWFuY2UgZnVuY3Rpb24uCiMnICQkCiMnIGYgPSBcbWJveHtpbnRlcmNlcHR9ICsgZl8xICsgZl8yIFxcCiMnIFxtYm94e2ludGVyY2VwdH0gXHNpbSBcbWJveHtub3JtYWx9KDAsMSlcXAojJyBmXzEgXHNpbSBcbWJveHtHUH0oMCxLXzEpXFwKIycgZl8yIFxzaW0gXG1ib3h7R1B9KDAsS18yKQojJyAkJAojJyB3aGVyZSB0aGUgZmlyc3QgR1AgdXNlcyB0aGUgZXhwb25lbnRpYXRlZCBxdWFkcmF0aWMgY292YXJpYW5jZQojJyBmdW5jdGlvbiwgYW5kIHRoZSBzZWNvbmQgb25lIGEgcGVyaW9kaWMgY292YXJpYW5jZSBmdW5jdGlvbi4gTW9zdAojJyB5ZWFycyBoYXZlIDM2NSBjYWxlbmRhciBkYXlzIGFuZCBldmVyeSBmb3VyIHllYXJzIChkdXJpbmcgdGhlIGRhdGEKIycgcmFuZ2UpIHRoZXJlIGFyZSAzNjYgZGF5cywgYW5kIHRodXMgd2Ugc2ltcGxpZnkgYW5kIHVzZSBwZXJpb2Qgb2YKIycgMzY1LjI1IGZvciB0aGUgcGVyaW9kaWMgY29tcG9uZW50LAojJwojJyBUaGUgZmlyc3QgdmVyc2lvbiBvZiBtb2RlbCAyIHdpdGggdGhlIGFkZGVkIHBlcmlvZGljIGNvbXBvbmVudAojJyBmb2xsb3dpbmcgZnJvbSBSaXV0b3J0LU1heW9sICgyMDIwKSB0dXJuZWQgb3V0IGJlIHZlcnkgc2xvdy4gV2l0aAojJyB0aGUgZGVmYXVsdCBNQ01DIG9wdGlvbnMgdGhlIGluZmVyZW5jZSB3b3VsZCBoYXZlIHRha2VuIGhvdXJzLCBidXQKIycgd2l0aCB0aGUgc2hvcnQgY2hhaW5zIGl0IHdhcyBwb3NzaWJsZSB0byBpbmZlciB0aGF0IHNvbWV0aGluZyBoYXMKIycgdG8gYmUgd3JvbmcuIFRoZSBtb2RlbCBvdXRwdXQgd2FzIHNlbnNpYmxlLCBidXQgZGlhZ25vc3RpY3MKIycgaW5kaWNhdGVkIHZlcnkgc2xvdyBtaXhpbmcuIEJ5IG1vcmUgY2FyZWZ1bCBleGFtaW5hdGlvbiBvZiB0aGUKIycgbW9kZWwgaXQgdHVybmVkIG91dCB0aGF0IHRoZSBwZXJpb2RpYyBjb21wb25lbnQgd2FzIGluY2x1ZGluZwojJyBhbm90aGVyIGludGVyY2VwdCB0ZXJtIGFuZCB3aXRoIHR3byBpbnRlcmNlcHQgdGVybXMgdGhlaXIgc3VtIHdhcwojJyB3ZWxsIGluZm9ybWVkIGJ5IHRoZSBkYXRhLCBidXQgaW5kaXZpZHVhbGx5IHRoZXkgd2VyZSBub3Qgd2VsbAojJyBpbmZvcm1lZCBhbmQgdGh1cyB0aGUgcG9zdGVyaW9ycyB3ZXJlIHdpZGUsIHdoaWNoIGxlYWQgdG8gdmVyeSBzbG93CiMnIG1peGluZy4gVGhpcyBiYWQgbW9kZWwgaXMgbm90IHNob3duIGhlcmUsIGJ1dCB0aGUgb3B0aW1pemF0aW9uLAojJyBzaG9ydCBNQ01DIGNoYWlucyBhbmQgc2FtcGxpbmcgZGlhZ25vc3RpYyB0b29scyB3ZXJlIGNydWNpYWwgZm9yCiMnIGZhc3QgZXhwZXJpbWVudGF0aW9uIGFuZCBzb2x2aW5nIHRoZSBwcm9ibGVtLgojJyAKIycgQ29tcGlsZSBTdGFuIG1vZGVsIDIgKHRoZSBmaXhlZCB2ZXJzaW9uKSBbZ3BiZjIuc3Rhbl0oaHR0cHM6Ly9naXRodWIuY29tL2F2ZWh0YXJpL2Nhc2VzdHVkaWVzL2Jsb2IvbWFzdGVyL0JpcnRoZGF5cy9ncGJmMi5zdGFuKQojKyBtb2RlbDIsIHJlc3VsdHM9J2hpZGUnCm1vZGVsMiA8LSBjbWRzdGFuX21vZGVsKHN0YW5fZmlsZSA9IHJvb3QoIkJpcnRoZGF5cyIsICJncGJmMi5zdGFuIiksCiAgICAgICAgICAgICAgICAgICAgICAgIGluY2x1ZGVfcGF0aHMgPSByb290KCJCaXJ0aGRheXMiKSkKCiMnIERhdGEgdG8gYmUgcGFzc2VkIHRvIFN0YW4Kc3RhbmRhdGEyIDwtIGxpc3QoeD1kYXRhJGlkLAogICAgICAgICAgICAgICAgICB5PWxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCksCiAgICAgICAgICAgICAgICAgIE49bGVuZ3RoKGRhdGEkaWQpLAogICAgICAgICAgICAgICAgICBjX2YxPTEuNSwgIyBmYWN0b3IgYyBvZiBiYXNpcyBmdW5jdGlvbnMgZm9yIEdQIGZvciBmMQogICAgICAgICAgICAgICAgICBNX2YxPTEwLCAgIyBudW1iZXIgb2YgYmFzaXMgZnVuY3Rpb25zIGZvciBHUCBmb3IgZjEKICAgICAgICAgICAgICAgICAgSl9mMj0yMCkgICMgbnVtYmVyIG9mIGJhc2lzIGZ1bmN0aW9ucyBmb3IgcGVyaW9kaWMgZjIKCiMnIE9wdGltaXppbmcgaXMgZmFzdGVyIHRoYW4gc2FtcGxpbmcgKGFsdGhvdWdoIHRoaXMgcmVzdWx0IGNhbiBiZQojJyB1c2VmdWwgaW4gYSBxdWljayB3b3JrZmxvdywgdGhlIHJlc3VsdCBzaG91bGQgbm90IGJlIHVzZWQgYXMgdGhlCiMnIGZpbmFsIHJlc3VsdCkuCiMrIG9wdDIsIHJlc3VsdHM9J2hpZGUnCm9wdDIgPC0gbW9kZWwyJG9wdGltaXplKGRhdGE9c3RhbmRhdGEyLCBpbml0PTAsIGFsZ29yaXRobT0nYmZncycpCgojJyBDaGVjayB3aGV0aGVyIHBhcmFtZXRlcnMgaGF2ZSByZWFzb25hYmxlIHZhbHVlcwpvZHJhd3MyIDwtIG9wdDIkZHJhd3MoKQpzdWJzZXQob2RyYXdzMiwgdmFyaWFibGU9YygnaW50ZXJjZXB0Jywnc2lnbWFfJywnbGVuZ3Roc2NhbGVfJywnc2lnbWEnKSwgcmVnZXg9VFJVRSkKCiMnIENvbXBhcmUgdGhlIG1vZGVsIHRvIHRoZSBkYXRhCkVmIDwtIGV4cChhcy5udW1lcmljKHN1YnNldChvZHJhd3MyLCB2YXJpYWJsZT0nZicpKSkKRWYxIDwtIGFzLm51bWVyaWMoc3Vic2V0KG9kcmF3czIsIHZhcmlhYmxlPSdmMScpKQpFZjEgPC0gZXhwKEVmMSAtIG1lYW4oRWYxKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCkVmMiA8LSBhcy5udW1lcmljKHN1YnNldChvZHJhd3MyLCB2YXJpYWJsZT0nZjInKSkKRWYyIDwtIGV4cChFZjIgLSBtZWFuKEVmMikgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpwZiA8LSBkYXRhICU+JQogIG11dGF0ZShFZiA9IEVmKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9saW5lKGFlcyh5PUVmKSwgY29sb3I9c2V0MVsxXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMiKQpwZjEgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYxID0gRWYxKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9saW5lKGFlcyh5PUVmMSksIGNvbG9yPXNldDFbMV0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIikKcGYyIDwtIGRhdGEgJT4lCiAgbXV0YXRlKEVmMiA9IEVmMikgJT4lCiAgZ3JvdXBfYnkoZGF5X29mX3llYXIyKSAlPiUKICBzdW1tYXJpc2UobWVhbmJpcnRocz1tZWFuKGJpcnRoc19yZWxhdGl2ZTEwMCksIG1lYW5FZjI9bWVhbihFZjIpKSAlPiUKICBnZ3Bsb3QoYWVzKHg9YXMuRGF0ZSgiMTk4Ny0xMi0zMSIpK2RheV9vZl95ZWFyMiwgeT1tZWFuYmlydGhzKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKSArCiAgZ2VvbV9saW5lKGFlcyh5PW1lYW5FZjIpLCBjb2xvcj1zZXQxWzFdKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyBvZiB5ZWFyIikKcGYgLyAocGYxICsgcGYyKQoKIycgU2FtcGxlIHNob3J0IGNoYWlucyB1c2luZyB0aGUgb3B0aW1pemF0aW9uIHJlc3VsdCBhcyBpbml0aWFsIHZhbHVlcwojJyAoYWx0aG91Z2ggdGhlIHJlc3VsdCBmcm9tIHNob3J0IGNoYWlucyBjYW4gYmUgdXNlZnVsIGluIGEgcXVpY2sKIycgd29ya2Zsb3csIHRoZSByZXN1bHQgc2hvdWxkIG5vdCBiZSB1c2VkIGFzIHRoZSBmaW5hbCByZXN1bHQpLgppbml0MiA8LSBzYXBwbHkoYygnaW50ZXJjZXB0JywnbGVuZ3Roc2NhbGVfZjEnLCdsZW5ndGhzY2FsZV9mMicsJ3NpZ21hX2YxJywnc2lnbWFfZjInLCdzaWdtYScsJ2JldGFfZjEnLCdiZXRhX2YyJyksCiAgICAgICAgICAgICAgICBmdW5jdGlvbih2YXJpYWJsZSkge2FzLm51bWVyaWMoc3Vic2V0KG9kcmF3czIsIHZhcmlhYmxlPXZhcmlhYmxlKSl9KQojKyBmaXQyLCByZXN1bHRzPSdoaWRlJwpmaXQyIDwtIG1vZGVsMiRzYW1wbGUoZGF0YT1zdGFuZGF0YTIsIGl0ZXJfd2FybXVwPTEwMCwgaXRlcl9zYW1wbGluZz0xMDAsCiAgICAgICAgICAgICAgICAgICAgICBjaGFpbnM9NCwgcGFyYWxsZWxfY2hhaW5zPTQsCiAgICAgICAgICAgICAgICAgICAgICBpbml0PWZ1bmN0aW9uKCkgeyBpbml0MiB9KQoKIycgQ2hlY2sgd2hldGhlciBwYXJhbWV0ZXJzIGhhdmUgcmVhc29uYWJsZSB2YWx1ZXMKZHJhd3MyIDwtIGZpdDIkZHJhd3MoKQpzdW1tYXJpc2VfZHJhd3Moc3Vic2V0KGRyYXdzMiwgdmFyaWFibGU9YygnaW50ZXJjZXB0Jywnc2lnbWFfJywnbGVuZ3Roc2NhbGVfJywnc2lnbWEnKSwgcmVnZXg9VFJVRSkpCgojJyBDb21wYXJlIHRoZSBtb2RlbCB0byB0aGUgZGF0YQpkcmF3czIgPC0gYXNfZHJhd3NfbWF0cml4KGRyYXdzMikKRWYgPC0gZXhwKGFwcGx5KHN1YnNldChkcmF3czIsIHZhcmlhYmxlPSdmJyksIDIsIG1lZGlhbikpCkVmMSA8LSBhcHBseShzdWJzZXQoZHJhd3MyLCB2YXJpYWJsZT0nZjEnKSwgMiwgbWVkaWFuKQpFZjEgPC0gZXhwKEVmMSAtIG1lYW4oRWYxKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCkVmMiA8LSBhcHBseShzdWJzZXQoZHJhd3MyLCB2YXJpYWJsZT0nZjInKSwgMiwgbWVkaWFuKQpFZjIgPC0gZXhwKEVmMiAtIG1lYW4oRWYyKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCnBmIDwtIGRhdGEgJT4lCiAgbXV0YXRlKEVmID0gRWYpICU+JQogIGdncGxvdChhZXMoeD1kYXRlLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBnZW9tX2xpbmUoYWVzKHk9RWYpLCBjb2xvcj1zZXQxWzFdKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyIpCnBmMSA8LSBkYXRhICU+JQogIG11dGF0ZShFZjEgPSBFZjEpICU+JQogIGdncGxvdChhZXMoeD1kYXRlLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBnZW9tX2xpbmUoYWVzKHk9RWYxKSwgY29sb3I9c2V0MVsxXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMiKQpwZjIgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYyID0gRWYyKSAlPiUKICBncm91cF9ieShkYXlfb2ZfeWVhcjIpICU+JQogIHN1bW1hcmlzZShtZWFuYmlydGhzPW1lYW4oYmlydGhzX3JlbGF0aXZlMTAwKSwgbWVhbkVmMj1tZWFuKEVmMikpICU+JQogIGdncGxvdChhZXMoeD1hcy5EYXRlKCIxOTg3LTEyLTMxIikrZGF5X29mX3llYXIyLCB5PW1lYW5iaXJ0aHMpKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCBkYXRlX2xhYmVscyA9ICIlYiIpICsKICBnZW9tX2xpbmUoYWVzKHk9bWVhbkVmMiksIGNvbG9yPXNldDFbMV0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIG9mIHllYXIiKQpwZiAvIChwZjEgKyBwZjIpCgojJyBTZWFzb25hbCBjb21wb25lbnQgaGFzIHJlYXNvbmFibGUgZml0IHRvIHRoZSBkYXRhLgojJyAKCiMnICMjIyBNb2RlbCAzOiBTbG93IHRyZW5kICsgeWVhcmx5IHNlYXNvbmFsIHRyZW5kICsgZGF5IG9mIHdlZWsKIycKIycgQmFzZWQgb24gdGhlIHF1aWNrIHBsb3R0aW5nIG9mIHRoZSBkYXRhIGFib3ZlLCBkYXkgb2Ygd2VlayBoYXMgYQojJyBjbGVhciBlZmZlY3QgYW5kIHRoZXJlIGFyZSBsZXNzIGJhYmllcyBib3JuIG9uIFNhdHVyZGF5IGFuZAojJyBTdW5kYXkuIFRoaXMgY2FuIGJlIHRha2VuIGludG8gYWNjb3VudCB3aXRoIHNpbXBsZSBhZGRpdGl2ZQojJyBjb2VmZmljaWVudHMuIFdlIGZpeCB0aGUgZWZmZWN0IG9mIE1vbmRheSB0byAwIGFuZCBoYXZlIGFkZGl0aW9uYWwKIycgY29lZmZpY2llbnRzIGZvciBvdGhlciB3ZWVrZGF5cy4KIycgJCQKIycgZiA9IFxtYm94e2ludGVyY2VwdH0gKyBmXzEgKyBmXzIgKyBcYmV0YV97XG1ib3h7ZGF5IG9mIHdlZWt9fSBcXAojJyBcbWJveHtpbnRlcmNlcHR9IFxzaW0gXG1ib3h7bm9ybWFsfSgwLDEpXFwKIycgZl8xIFxzaW0gXG1ib3h7R1B9KDAsS18xKVxcCiMnIGZfMiBcc2ltIFxtYm94e0dQfSgwLEtfMilcXAojJyBcYmV0YV97XG1ib3h7ZGF5IG9mIHdlZWt9fSA9IDAgXHF1YWQgXG1ib3h7aWYgZGF5IG9mIHdlZWsgaXMgTW9uZGF5fVxcCiMnIFxiZXRhX3tcbWJveHtkYXkgb2Ygd2Vla319IFxzaW0gXG1ib3h7bm9ybWFsfSgwLDEpIFxxdWFkIFxtYm94e2lmIGRheSBvZiB3ZWVrIGlzIG5vdCBNb25kYXl9CiMnICQkCiMnIAojJyBDb21waWxlIFN0YW4gbW9kZWwgMyBbZ3BiZjMuc3Rhbl0oaHR0cHM6Ly9naXRodWIuY29tL2F2ZWh0YXJpL2Nhc2VzdHVkaWVzL2Jsb2IvbWFzdGVyL0JpcnRoZGF5cy9ncGJmMy5zdGFuKQojKyBtb2RlbDMsIHJlc3VsdHM9J2hpZGUnCm1vZGVsMyA8LSBjbWRzdGFuX21vZGVsKHN0YW5fZmlsZSA9IHJvb3QoIkJpcnRoZGF5cyIsICJncGJmMy5zdGFuIiksCiAgICAgICAgICAgICAgICAgICAgICAgIGluY2x1ZGVfcGF0aHMgPSByb290KCJCaXJ0aGRheXMiKSkKCiMnIERhdGEgdG8gYmUgcGFzc2VkIHRvIFN0YW4Kc3RhbmRhdGEzIDwtIGxpc3QoeD1kYXRhJGlkLAogICAgICAgICAgICAgICAgICB5PWxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCksCiAgICAgICAgICAgICAgICAgIE49bGVuZ3RoKGRhdGEkaWQpLAogICAgICAgICAgICAgICAgICBjX2YxPTEuNSwgIyBmYWN0b3IgYyBvZiBiYXNpcyBmdW5jdGlvbnMgZm9yIEdQIGZvciBmMQogICAgICAgICAgICAgICAgICBNX2YxPTEwLCAgIyBudW1iZXIgb2YgYmFzaXMgZnVuY3Rpb25zIGZvciBHUCBmb3IgZjEKICAgICAgICAgICAgICAgICAgSl9mMj0yMCwgICMgbnVtYmVyIG9mIGJhc2lzIGZ1bmN0aW9ucyBmb3IgcGVyaW9kaWMgZjIKICAgICAgICAgICAgICAgICAgZGF5X29mX3dlZWs9ZGF0YSRkYXlfb2Zfd2VlaykKCiMnIE9wdGltaXppbmcgaXMgZmFzdGVyIHRoYW4gc2FtcGxpbmcgKGFsdGhvdWdoIHRoaXMgcmVzdWx0IGNhbiBiZQojJyB1c2VmdWwgaW4gYSBxdWljayB3b3JrZmxvdywgdGhlIHJlc3VsdCBzaG91bGQgbm90IGJlIHVzZWQgYXMgdGhlCiMnIGZpbmFsIHJlc3VsdCkuCiMrIG9wdDMsIHJlc3VsdHM9J2hpZGUnCm9wdDMgPC0gbW9kZWwzJG9wdGltaXplKGRhdGE9c3RhbmRhdGEzLCBpbml0PTAsIGFsZ29yaXRobT0nYmZncycpCgojJyBDaGVjayB3aGV0aGVyIHBhcmFtZXRlcnMgaGF2ZSByZWFzb25hYmxlIHZhbHVlcwpvZHJhd3MzIDwtIG9wdDMkZHJhd3MoKQpzdWJzZXQob2RyYXdzMywgdmFyaWFibGU9YygnaW50ZXJjZXB0Jywnc2lnbWFfJywnbGVuZ3Roc2NhbGVfJywnc2lnbWEnKSwgcmVnZXg9VFJVRSkKc3Vic2V0KG9kcmF3czMsIHZhcmlhYmxlPWMoJ2JldGFfZjMnKSkKCiMnIENvbXBhcmUgdGhlIG1vZGVsIHRvIHRoZSBkYXRhCkVmIDwtIGV4cChhcy5udW1lcmljKHN1YnNldChvZHJhd3MzLCB2YXJpYWJsZT0nZicpKSkKRWYxIDwtIGFzLm51bWVyaWMoc3Vic2V0KG9kcmF3czMsIHZhcmlhYmxlPSdmMScpKQpFZjEgPC0gZXhwKEVmMSAtIG1lYW4oRWYxKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCkVmMiA8LSBhcy5udW1lcmljKHN1YnNldChvZHJhd3MzLCB2YXJpYWJsZT0nZjInKSkKRWYyIDwtIGV4cChFZjIgLSBtZWFuKEVmMikgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZl9kYXlfb2Zfd2VlayA8LSBhcy5udW1lcmljKHN1YnNldChvZHJhd3MzLCB2YXJpYWJsZT0nZl9kYXlfb2Zfd2VlaycpKQpFZl9kYXlfb2Zfd2VlayA8LSBleHAoRWZfZGF5X29mX3dlZWsgLSBtZWFuKEVmX2RheV9vZl93ZWVrKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCnBmIDwtIGRhdGEgJT4lCiAgbXV0YXRlKEVmID0gRWYpICU+JQogIGdncGxvdChhZXMoeD1kYXRlLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBnZW9tX2xpbmUoYWVzKHk9RWYpLCBjb2xvcj1zZXQxWzFdLCBhbHBoYT0wLjc1KSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyIpCnBmMSA8LSBkYXRhICU+JQogIG11dGF0ZShFZjEgPSBFZjEpICU+JQogIGdncGxvdChhZXMoeD1kYXRlLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBnZW9tX2xpbmUoYWVzKHk9RWYxKSwgY29sb3I9c2V0MVsxXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMiKQpwZjIgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYyID0gRWYyKSAlPiUKICBncm91cF9ieShkYXlfb2ZfeWVhcjIpICU+JQogIHN1bW1hcmlzZShtZWFuYmlydGhzPW1lYW4oYmlydGhzX3JlbGF0aXZlMTAwKSwgbWVhbkVmMj1tZWFuKEVmMikpICU+JQogIGdncGxvdChhZXMoeD1hcy5EYXRlKCIxOTg3LTEyLTMxIikrZGF5X29mX3llYXIyLCB5PW1lYW5iaXJ0aHMpKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCBkYXRlX2xhYmVscyA9ICIlYiIpICsKICBnZW9tX2xpbmUoYWVzKHk9bWVhbkVmMiksIGNvbG9yPXNldDFbMV0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIG9mIHllYXIiKQpwZjMgPC0gZ2dwbG90KGRhdGE9ZGF0YSwgYWVzKHg9ZGF5X29mX3dlZWssIHk9YmlydGhzX3JlbGF0aXZlMTAwKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSAxOjcsIGxhYmVscz1jKCdNb24nLCdUdWUnLCdXZWQnLCdUaHUnLCdGcmknLCdTYXQnLCdTdW4nKSkgKwogIGdlb21fbGluZShkYXRhPWRhdGEuZnJhbWUoeD0xOjcseT1FZl9kYXlfb2Zfd2VlayksIGFlcyh4PXgsIHk9RWZfZGF5X29mX3dlZWspLCBjb2xvcj1zZXQxWzFdKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyBvZiB3ZWVrIikKKHBmICsgcGYxKSAvIChwZjIgKyBwZjMpCgojJyBTYW1wbGUgc2hvcnQgY2hhaW5zIHVzaW5nIHRoZSBvcHRpbWl6YXRpb24gcmVzdWx0IGFzIGluaXRpYWwgdmFsdWVzCiMnIChhbHRob3VnaCB0aGUgcmVzdWx0IGZyb20gc2hvcnQgY2hhaW5zIGNhbiBiZSB1c2VmdWwgaW4gYSBxdWljawojJyB3b3JrZmxvdywgdGhlIHJlc3VsdCBzaG91bGQgbm90IGJlIHVzZWQgYXMgdGhlIGZpbmFsIHJlc3VsdCkuCmluaXQzIDwtIHNhcHBseShjKCdpbnRlcmNlcHQwJywnbGVuZ3Roc2NhbGVfZjEnLCdsZW5ndGhzY2FsZV9mMicsJ3NpZ21hX2YxJywnc2lnbWFfZjInLCdzaWdtYScsCiAgICAgICAgICAgICAgICAgICdiZXRhX2YxJywnYmV0YV9mMicsJ2JldGFfZjMnKSwKICAgICAgICAgICAgICAgIGZ1bmN0aW9uKHZhcmlhYmxlKSB7YXMubnVtZXJpYyhzdWJzZXQob2RyYXdzMywgdmFyaWFibGU9dmFyaWFibGUpKX0pCiMrIGZpdDMsIHJlc3VsdHM9J2hpZGUnCmZpdDMgPC0gbW9kZWwzJHNhbXBsZShkYXRhPXN0YW5kYXRhMywgaXRlcl93YXJtdXA9MTAwLCBpdGVyX3NhbXBsaW5nPTEwMCwKICAgICAgICAgICAgICAgICAgICAgIGNoYWlucz00LCBwYXJhbGxlbF9jaGFpbnM9NCwKICAgICAgICAgICAgICAgICAgICAgIGluaXQ9ZnVuY3Rpb24oKSB7IGluaXQzIH0pCgojJyBDaGVjayB3aGV0aGVyIHBhcmFtZXRlcnMgaGF2ZSByZWFzb25hYmxlIHZhbHVlcwpkcmF3czMgPC0gZml0MyRkcmF3cygpCnN1bW1hcmlzZV9kcmF3cyhzdWJzZXQoZHJhd3MzLCB2YXJpYWJsZT1jKCdpbnRlcmNlcHQnLCdzaWdtYV8nLCdsZW5ndGhzY2FsZV8nLCdzaWdtYScpLCByZWdleD1UUlVFKSkKc3VtbWFyaXNlX2RyYXdzKHN1YnNldChkcmF3czMsIHZhcmlhYmxlPWMoJ2JldGFfZjMnKSkpCgojJyBDb21wYXJlIHRoZSBtb2RlbCB0byB0aGUgZGF0YQpkcmF3czMgPC0gYXNfZHJhd3NfbWF0cml4KGRyYXdzMykKRWYgPC0gZXhwKGFwcGx5KHN1YnNldChkcmF3czMsIHZhcmlhYmxlPSdmJyksIDIsIG1lZGlhbikpCkVmMSA8LSBhcHBseShzdWJzZXQoZHJhd3MzLCB2YXJpYWJsZT0nZjEnKSwgMiwgbWVkaWFuKQpFZjEgPC0gZXhwKEVmMSAtIG1lYW4oRWYxKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCkVmMiA8LSBhcHBseShzdWJzZXQoZHJhd3MzLCB2YXJpYWJsZT0nZjInKSwgMiwgbWVkaWFuKQpFZjIgPC0gZXhwKEVmMiAtIG1lYW4oRWYyKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCkVmX2RheV9vZl93ZWVrIDwtIGFwcGx5KHN1YnNldChkcmF3czMsIHZhcmlhYmxlPSdmX2RheV9vZl93ZWVrJyksIDIsIG1lZGlhbikKRWZfZGF5X29mX3dlZWsgPC0gZXhwKEVmX2RheV9vZl93ZWVrIC0gbWVhbihFZl9kYXlfb2Zfd2VlaykgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpwZiA8LSBkYXRhICU+JQogIG11dGF0ZShFZiA9IEVmKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9saW5lKGFlcyh5PUVmKSwgY29sb3I9c2V0MVsxXSwgYWxwaGE9MC43NSkgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMiKQpwZjEgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYxID0gRWYxKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9saW5lKGFlcyh5PUVmMSksIGNvbG9yPXNldDFbMV0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIikKcGYyIDwtIGRhdGEgJT4lCiAgbXV0YXRlKEVmMiA9IEVmMikgJT4lCiAgZ3JvdXBfYnkoZGF5X29mX3llYXIyKSAlPiUKICBzdW1tYXJpc2UobWVhbmJpcnRocz1tZWFuKGJpcnRoc19yZWxhdGl2ZTEwMCksIG1lYW5FZjI9bWVhbihFZjIpKSAlPiUKICBnZ3Bsb3QoYWVzKHg9YXMuRGF0ZSgiMTk4Ny0xMi0zMSIpK2RheV9vZl95ZWFyMiwgeT1tZWFuYmlydGhzKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKSArCiAgZ2VvbV9saW5lKGFlcyh5PW1lYW5FZjIpLCBjb2xvcj1zZXQxWzFdKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyBvZiB5ZWFyIikKcGYzIDwtIGdncGxvdChkYXRhPWRhdGEsIGFlcyh4PWRheV9vZl93ZWVrLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gMTo3LCBsYWJlbHM9YygnTW9uJywnVHVlJywnV2VkJywnVGh1JywnRnJpJywnU2F0JywnU3VuJykpICsKICBnZW9tX2xpbmUoZGF0YT1kYXRhLmZyYW1lKHg9MTo3LHk9RWZfZGF5X29mX3dlZWspLCBhZXMoeD14LCB5PUVmX2RheV9vZl93ZWVrKSwgY29sb3I9c2V0MVsxXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgb2Ygd2VlayIpCihwZiArIHBmMSkgLyAocGYyICsgcGYzKQoKIycgV2Vla2RheSBlZmZlY3RzIGFyZSBlYXN5IHRvIGVzdGltYXRlIGFzIHRoZXJlIGFyZSBhYm91dCB0aG91c2FuZAojJyBvYnNlcnZhdGlvbnMgcGVyIHdlZWtkYXkuCiMnIAoKIycgIyMjIE1vZGVsIDQ6IGxvbmcgdGVybSBzbW9vdGggKyBzZWFzb25hbCArIHdlZWtkYXkgd2l0aCBpbmNyZWFzaW5nIG1hZ25pdHVkZQojJwojJyBMb29raW5nIGF0IHRoZSB0aW1lIHNlcmllcyBvZiB3aG9sZSBkYXRhIHdlIHNlZSB0aGUgZG90cwojJyByZXByZXNlbnRpbmcgdGhlIGRhaWx5IHZhbHVlcyBmb3JtaW5nIHRocmVlIGJyYW5jaGVzIHRoYXQgYXJlCiMnIGdldHRpbmcgZnVydGhlciBhd2F5IGZyb20gZWFjaCBvdGhlci4gSW4gcHJldmlvdXMgYW5hbHlzaXMgKEJEQTMpCiMnIHdlIGFsc28gaGFkIGEgbW9kZWwgY29tcG9uZW50IGFsbG93aW5nIGdyYWR1YWxseSBjaGFuZ2luZyBlZmZlY3QKIycgZm9yIGRheSBvZiB3ZWVrIGFuZCBkaWQgb2JzZXJ2ZSB0aGF0IHRoZSBlZmZlY3Qgb2YgU2F0dXJkYXkgYW5kCiMnIFN1bmRheSBkaWQgZ2V0IHN0cm9uZ2VyIGluIHRpbWUuIFRoZSBuZXh0IG1vZGVsIGluY2x1ZGVzIHRpbWUKIycgZGVwZW5kZW50IG1hZ25pdHVkZSBjb21wb25lbnQgZm9yIHRoZSBkYXkgb2Ygd2VlayBlZmZlY3QuCiMnICQkCiMnIGYgPSBcbWJveHtpbnRlcmNlcHR9ICsgZl8xICsgZl8yICsgXGV4cChnXzMpXGJldGFfe1xtYm94e2RheSBvZiB3ZWVrfX0gXFwKIycgXG1ib3h7aW50ZXJjZXB0fSBcc2ltIFxtYm94e25vcm1hbH0oMCwxKVxcCiMnIGZfMSBcc2ltIFxtYm94e0dQfSgwLEtfMSlcXAojJyBmXzIgXHNpbSBcbWJveHtHUH0oMCxLXzIpXFwKIycgZ18zIFxzaW0gXG1ib3h7R1B9KDAsS18zKVxcCiMnIFxiZXRhX3tcbWJveHtkYXkgb2Ygd2Vla319ID0gMCBccXVhZCBcbWJveHtpZiBkYXkgb2Ygd2VlayBpcyBNb25kYXl9XFwKIycgXGJldGFfe1xtYm94e2RheSBvZiB3ZWVrfX0gXHNpbSBcbWJveHtub3JtYWx9KDAsMSkgXHF1YWQgXG1ib3h7aWYgZGF5IG9mIHdlZWsgaXMgbm90IE1vbmRheX0KIycgJCQKIycgVGhlIG1hZ25pdHVkZSBvZiB0aGUgd2Vla2RheSBlZmZlY3QgaXMgbW9kZWxsZWQgd2l0aCAkXGV4cChnXzMpJCwKIycgd2hlcmUgJGdfMyQgaGFzIEdQIHByaW9yIHdpdGggemVybyBtZWFuIGFuZCBleHBvbmVudGlhdGVkIHF1YWRyYXRpYwojJyBjb3ZhcmlhbmNlIGZ1bmN0aW9uLgojJyAKIycgQ29tcGlsZSBTdGFuIG1vZGVsIDQgW2dwYmY0LnN0YW5dKGh0dHBzOi8vZ2l0aHViLmNvbS9hdmVodGFyaS9jYXNlc3R1ZGllcy9ibG9iL21hc3Rlci9CaXJ0aGRheXMvZ3BiZjQuc3RhbikKIysgbW9kZWw0LCByZXN1bHRzPSdoaWRlJwptb2RlbDQgPC0gY21kc3Rhbl9tb2RlbChzdGFuX2ZpbGUgPSByb290KCJCaXJ0aGRheXMiLCAiZ3BiZjQuc3RhbiIpLAogICAgICAgICAgICAgICAgICAgICAgICBpbmNsdWRlX3BhdGhzID0gcm9vdCgiQmlydGhkYXlzIikpCgojJyBEYXRhIHRvIGJlIHBhc3NlZCB0byBTdGFuCnN0YW5kYXRhNCA8LSBsaXN0KHg9ZGF0YSRpZCwKICAgICAgICAgICAgICAgICAgeT1sb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApLAogICAgICAgICAgICAgICAgICBOPWxlbmd0aChkYXRhJGlkKSwKICAgICAgICAgICAgICAgICAgY19mMT0xLjUsICMgZmFjdG9yIGMgb2YgYmFzaXMgZnVuY3Rpb25zIGZvciBHUCBmb3IgZjEKICAgICAgICAgICAgICAgICAgTV9mMT0xMCwgICMgbnVtYmVyIG9mIGJhc2lzIGZ1bmN0aW9ucyBmb3IgR1AgZm9yIGYxCiAgICAgICAgICAgICAgICAgIEpfZjI9MjAsICAjIG51bWJlciBvZiBiYXNpcyBmdW5jdGlvbnMgZm9yIHBlcmlvZGljIGYyCiAgICAgICAgICAgICAgICAgIGNfZzM9MS41LCAjIGZhY3RvciBjIG9mIGJhc2lzIGZ1bmN0aW9ucyBmb3IgR1AgZm9yIGczCiAgICAgICAgICAgICAgICAgIE1fZzM9NSwgICAjIG51bWJlciBvZiBiYXNpcyBmdW5jdGlvbnMgZm9yIEdQIGZvciBnMwogICAgICAgICAgICAgICAgICBkYXlfb2Zfd2Vlaz1kYXRhJGRheV9vZl93ZWVrKSAKCiMnIEFzIHdlIGhhdmUgaW5jcmVhc2VkIHRoZSBjb21wbGV4aXR5IG9mIHRoZSBtb2RlbCwgdGhlIG1vZGUgc3RhcnRzCiMnIHRvIGJlIGxlc3MgYW5kIGxlc3MgcmVwcmVzZW50YXRpdmUgb2YgdGhlIHBvc3Rlcmlvci4gV2Ugc3RpbGwgdXNlCiMnIHRoZSBvcHRpbWl6YXRpb24gdG8gY2hlY2sgdGhhdCBjb2RlIHJldHVybnMgc29tZXRoaW5nIHJlYXNvbmFibGUKIycgYW5kIGFzIGluaXRpYWwgdmFsdWVzIGZvciBNQ01DLCBidXQgd2Ugbm93IHN0b3AgdGhlIG9wdGltaXphdGlvbgojJyBlYXJseS4gQnkgYWRkaW5nIGB0b2xfb2JqPTEwYCBhcmd1bWVudCwgdGhlIG9wdGltaXphdGlvbiBzdG9wcyB3aGVuCiMnIHRoZSBjaGFuZ2UgaW4gdGhlIGxvZyBwb3N0ZXJpb3IgZGVuc2l0eSBpcyBsZXNzIHRoYW4gMTAsIHdoaWNoIGlzCiMnIGxpa2VseSB0byBoYXBwZW5lZCBiZWZvcmUgcmVhY2hpbmcgdGhlIG1vZGUuCiMrIG9wdDQsIHJlc3VsdHM9J2hpZGUnCm9wdDQgPC0gbW9kZWw0JG9wdGltaXplKGRhdGE9c3RhbmRhdGE0LCBpbml0PTAsIGFsZ29yaXRobT0nYmZncycsIHRvbF9vYmo9MTApCgojJyBDaGVjayB3aGV0aGVyIHBhcmFtZXRlcnMgaGF2ZSByZWFzb25hYmxlIHZhbHVlcwpvZHJhd3M0IDwtIG9wdDQkZHJhd3MoKQpzdWJzZXQob2RyYXdzNCwgdmFyaWFibGU9YygnaW50ZXJjZXB0Jywnc2lnbWFfJywnbGVuZ3Roc2NhbGVfJywnc2lnbWEnKSwgcmVnZXg9VFJVRSkKc3Vic2V0KG9kcmF3czQsIHZhcmlhYmxlPWMoJ2JldGFfZjMnKSkKCiMnIENvbXBhcmUgdGhlIG1vZGVsIHRvIHRoZSBkYXRhCkVmIDwtIGV4cChhcy5udW1lcmljKHN1YnNldChvZHJhd3M0LCB2YXJpYWJsZT0nZicpKSkKRWYxIDwtIGFzLm51bWVyaWMoc3Vic2V0KG9kcmF3czQsIHZhcmlhYmxlPSdmMScpKQpFZjEgPC0gZXhwKEVmMSAtIG1lYW4oRWYxKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCkVmMiA8LSBhcy5udW1lcmljKHN1YnNldChvZHJhd3M0LCB2YXJpYWJsZT0nZjInKSkKRWYyIDwtIGV4cChFZjIgLSBtZWFuKEVmMikgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZl9kYXlfb2Zfd2VlayA8LSBhcy5udW1lcmljKHN1YnNldChvZHJhd3M0LCB2YXJpYWJsZT0nZl9kYXlfb2Zfd2VlaycpKQpFZl9kYXlfb2Zfd2VlayA8LSBleHAoRWZfZGF5X29mX3dlZWsgLSBtZWFuKEVmX2RheV9vZl93ZWVrKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCkVmMyA8LSBhcy5udW1lcmljKHN1YnNldChvZHJhd3M0LCB2YXJpYWJsZT0nZjMnKSkKRWYzIDwtIGV4cChFZjMgLSBtZWFuKEVmMykgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpwZiA8LSBkYXRhICU+JQogIG11dGF0ZShFZiA9IEVmKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9saW5lKGFlcyh5PUVmKSwgY29sb3I9c2V0MVsxXSwgYWxwaGE9MC43NSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMiKQpwZjEgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYxID0gRWYxKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9saW5lKGFlcyh5PUVmMSksIGNvbG9yPXNldDFbMV0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIikKcGYyIDwtIGRhdGEgJT4lCiAgbXV0YXRlKEVmMiA9IEVmMikgJT4lCiAgZ3JvdXBfYnkoZGF5X29mX3llYXIyKSAlPiUKICBzdW1tYXJpc2UobWVhbmJpcnRocz1tZWFuKGJpcnRoc19yZWxhdGl2ZTEwMCksIG1lYW5FZjI9bWVhbihFZjIpKSAlPiUKICBnZ3Bsb3QoYWVzKHg9YXMuRGF0ZSgiMTk4Ny0xMi0zMSIpK2RheV9vZl95ZWFyMiwgeT1tZWFuYmlydGhzKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKSArCiAgZ2VvbV9saW5lKGFlcyh5PW1lYW5FZjIpLCBjb2xvcj1zZXQxWzFdKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyBvZiB5ZWFyIikKcGYzIDwtIGdncGxvdChkYXRhPWRhdGEsIGFlcyh4PWRheV9vZl93ZWVrLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gMTo3LCBsYWJlbHM9YygnTW9uJywnVHVlJywnV2VkJywnVGh1JywnRnJpJywnU2F0JywnU3VuJykpICsKICBnZW9tX2xpbmUoZGF0YT1kYXRhLmZyYW1lKHg9MTo3LHk9RWZfZGF5X29mX3dlZWspLCBhZXMoeD14LCB5PUVmX2RheV9vZl93ZWVrKSwgY29sb3I9c2V0MVsxXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgb2Ygd2VlayIpCnBmM2IgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYzID0gRWYzKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDAvRWYxL0VmMioxMDAqMTAwKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIGdlb21fcG9pbnQoYWVzKHk9RWYzKSwgY29sb3I9c2V0MVsxXSwgc2l6ZT0wLjEpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIikKKHBmICsgcGYxKSAvIChwZjIgKyBwZjNiKQoKIycgU2FtcGxlIHNob3J0IGNoYWlucyB1c2luZyB0aGUgZWFybHkgc3RvcHBlZCBvcHRpbWl6YXRpb24gcmVzdWx0IGFzCiMnIGluaXRpYWwgdmFsdWVzIChhbHRob3VnaCB0aGUgcmVzdWx0IGZyb20gc2hvcnQgY2hhaW5zIGNhbiBiZSB1c2VmdWwKIycgaW4gYSBxdWljayB3b3JrZmxvdywgdGhlIHJlc3VsdCBzaG91bGQgbm90IGJlIHVzZWQgYXMgdGhlIGZpbmFsCiMnIHJlc3VsdCkuCmluaXQ0IDwtIHNhcHBseShjKCdpbnRlcmNlcHQwJywnbGVuZ3Roc2NhbGVfZjEnLCdsZW5ndGhzY2FsZV9mMicsJ2xlbmd0aHNjYWxlX2czJywKICAgICAgICAgICAgICAgICAgJ3NpZ21hX2YxJywnc2lnbWFfZjInLCdzaWdtYV9nMycsJ3NpZ21hJywKICAgICAgICAgICAgICAgICAgJ2JldGFfZjEnLCdiZXRhX2YyJywnYmV0YV9mMycsJ2JldGFfZzMnKSwKICAgICAgICAgICAgICAgIGZ1bmN0aW9uKHZhcmlhYmxlKSB7YXMubnVtZXJpYyhzdWJzZXQob2RyYXdzNCwgdmFyaWFibGU9dmFyaWFibGUpKX0pCiMrIGZpdDQsIHJlc3VsdHM9J2hpZGUnCmZpdDQgPC0gbW9kZWw0JHNhbXBsZShkYXRhPXN0YW5kYXRhNCwgaXRlcl93YXJtdXA9MTAwLCBpdGVyX3NhbXBsaW5nPTEwMCwKICAgICAgICAgICAgICAgICAgICAgIGNoYWlucz00LCBwYXJhbGxlbF9jaGFpbnM9NCwKICAgICAgICAgICAgICAgICAgICAgIGluaXQ9ZnVuY3Rpb24oKSB7IGluaXQ0IH0sIHJlZnJlc2g9MTApCgojJyBDaGVjayB3aGV0aGVyIHBhcmFtZXRlcnMgaGF2ZSByZWFzb25hYmxlIHZhbHVlcwpkcmF3czQgPC0gZml0NCRkcmF3cygpCnN1bW1hcmlzZV9kcmF3cyhzdWJzZXQoZHJhd3M0LCB2YXJpYWJsZT1jKCdpbnRlcmNlcHQnLCdzaWdtYV8nLCdsZW5ndGhzY2FsZV8nLCdzaWdtYScpLCByZWdleD1UUlVFKSkKc3VtbWFyaXNlX2RyYXdzKHN1YnNldChkcmF3czQsIHZhcmlhYmxlPWMoJ2JldGFfZjMnKSkpCgojJyBDb21wYXJlIHRoZSBtb2RlbCB0byB0aGUgZGF0YQpkcmF3czQgPC0gYXNfZHJhd3NfbWF0cml4KGRyYXdzNCkKRWYgPC0gZXhwKGFwcGx5KHN1YnNldChkcmF3czQsIHZhcmlhYmxlPSdmJyksIDIsIG1lZGlhbikpCkVmMSA8LSBhcHBseShzdWJzZXQoZHJhd3M0LCB2YXJpYWJsZT0nZjEnKSwgMiwgbWVkaWFuKQpFZjEgPC0gZXhwKEVmMSAtIG1lYW4oRWYxKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCkVmMiA8LSBhcHBseShzdWJzZXQoZHJhd3M0LCB2YXJpYWJsZT0nZjInKSwgMiwgbWVkaWFuKQpFZjIgPC0gZXhwKEVmMiAtIG1lYW4oRWYyKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCkVmX2RheV9vZl93ZWVrIDwtIGFwcGx5KHN1YnNldChkcmF3czQsIHZhcmlhYmxlPSdmX2RheV9vZl93ZWVrJyksIDIsIG1lZGlhbikKRWZfZGF5X29mX3dlZWsgPC0gZXhwKEVmX2RheV9vZl93ZWVrIC0gbWVhbihFZl9kYXlfb2Zfd2VlaykgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZjMgPC0gYXBwbHkoc3Vic2V0KGRyYXdzNCwgdmFyaWFibGU9J2YzJyksIDIsIG1lZGlhbikKRWYzIDwtIGV4cChFZjMgLSBtZWFuKEVmMykgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpwZiA8LSBkYXRhICU+JQogIG11dGF0ZShFZiA9IEVmKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9saW5lKGFlcyh5PUVmKSwgY29sb3I9c2V0MVsxXSwgYWxwaGE9MC43NSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMiKQpwZjEgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYxID0gRWYxKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9saW5lKGFlcyh5PUVmMSksIGNvbG9yPXNldDFbMV0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIikKcGYyIDwtIGRhdGEgJT4lCiAgbXV0YXRlKEVmMiA9IEVmMikgJT4lCiAgZ3JvdXBfYnkoZGF5X29mX3llYXIyKSAlPiUKICBzdW1tYXJpc2UobWVhbmJpcnRocz1tZWFuKGJpcnRoc19yZWxhdGl2ZTEwMCksIG1lYW5FZjI9bWVhbihFZjIpKSAlPiUKICBnZ3Bsb3QoYWVzKHg9YXMuRGF0ZSgiMTk4Ny0xMi0zMSIpK2RheV9vZl95ZWFyMiwgeT1tZWFuYmlydGhzKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKSArCiAgZ2VvbV9saW5lKGFlcyh5PW1lYW5FZjIpLCBjb2xvcj1zZXQxWzFdKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyBvZiB5ZWFyIikKcGYzIDwtIGdncGxvdChkYXRhPWRhdGEsIGFlcyh4PWRheV9vZl93ZWVrLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gMTo3LCBsYWJlbHM9YygnTW9uJywnVHVlJywnV2VkJywnVGh1JywnRnJpJywnU2F0JywnU3VuJykpICsKICBnZW9tX2xpbmUoZGF0YT1kYXRhLmZyYW1lKHg9MTo3LHk9RWZfZGF5X29mX3dlZWspLCBhZXMoeD14LCB5PUVmX2RheV9vZl93ZWVrKSwgY29sb3I9c2V0MVsxXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgb2Ygd2VlayIpCnBmM2IgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYzID0gRWYzKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDAvRWYxL0VmMioxMDAqMTAwKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIGdlb21fcG9pbnQoYWVzKHk9RWYzKSwgY29sb3I9c2V0MVsxXSwgc2l6ZT0wLjEpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIikKKHBmICsgcGYxKSAvIChwZjIgKyBwZjNiKQoKIycgVGhlIG1vZGVsIGZpdHMgd2VsbCB0aGUgZGlmZmVyZW50IGJyYW5jaGVzIHZpc2libGUgaW4gcGxvdHRlZCBkYWlseQojJyByZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzLCB0aGF0IGlzLCBpdCBpcyBhYmxlIHRvIG1vZGVsIHRoZQojJyBpbmNyZWFzaW5nIHdlZWtlbmQgZWZmZWN0LgojJyAKCiMnICMjIyBNb2RlbCA1OiBsb25nIHRlcm0gc21vb3RoICsgc2Vhc29uYWwgKyB3ZWVrZGF5IHdpdGggdGltZSBkZXBlbmRlbnQgbWFnbml0dWRlICsgZGF5IG9mIHllYXIgUkhTCiMnCiMnIFRoZSBuZXh0IGNvbXBvbmVudCB0byBhZGQgaXMgZGF5IG9mIHllYXIgZWZmZWN0LiBNYW55IGJhbmsgaG9saWRheXMKIycgYXJlIGV2ZXJ5IHllYXIgb24gdGhlIHNhbWUgZGF5IG9mIHllYXIgYW5kIHRoZXJlIG1pZ2h0IGJlIGFsc28KIycgb3RoZXIgc3BlY2lhbCBkYXlzIHRoYXQgYXJlIGZhdm9yZWQgb3IgZGlzZmF2b3JlZC4KIycKIycgJCQKIycgZiA9IFxtYm94e2ludGVyY2VwdH0gKyBmXzEgKyBmXzIgKyBcZXhwKGdfMylcYmV0YV97XG1ib3h7ZGF5IG9mIHdlZWt9fSArIFxiZXRhX3tcbWJveHtkYXkgb2YgeWVhcn19XFwKIycgXG1ib3h7aW50ZXJjZXB0fSBcc2ltIFxtYm94e25vcm1hbH0oMCwxKVxcCiMnIGZfMSBcc2ltIFxtYm94e0dQfSgwLEtfMSlcXAojJyBmXzIgXHNpbSBcbWJveHtHUH0oMCxLXzIpXFwKIycgZ18zIFxzaW0gXG1ib3h7R1B9KDAsS18zKVxcCiMnIFxiZXRhX3tcbWJveHtkYXkgb2Ygd2Vla319ID0gMCBccXVhZCBcbWJveHtpZiBkYXkgb2Ygd2VlayBpcyBNb25kYXl9XFwKIycgXGJldGFfe1xtYm94e2RheSBvZiB3ZWVrfX0gXHNpbSBcbWJveHtub3JtYWx9KDAsMSkgXHF1YWQgXG1ib3h7aWYgZGF5IG9mIHdlZWsgaXMgbm90IE1vbmRheX1cXAojJyBcYmV0YV97XG1ib3h7ZGF5IG9mIHllYXJ9fSBcc2ltIFJIUygwLDAuMSkKIycgJCQKIycgQXMgd2UgYXNzdW1lIHRoYXQgb25seSBzb21lIGRheXMgb2YgeWVhciBhcmUgc3BlY2lhbCwgd2UgdXNlCiMnIHJlZ3VsYXJpemVkIGhvcnNlc2hvZSAoUkhTKSBwcmlvciBmb3IgZGF5IG9mIHllYXIgZWZmZWN0cy4KIycKIycgQXQgdGhpcyBwb2ludCB0aGUgb3B0aW1pemF0aW9uIGRpZG4ndCBwcm9kdWNlIHJlYXNvbmFibGUgcmVzdWx0IGFzCiMnIGVhcmxpZXIgYW5kIHNhbXBsaW5nIHR1cm5lZCBvdXQgdG8gYmUgdmVyeSBzbG93LiBXZSBhc3N1bWVkIHRoZQojJyBvcHRpbWl6YXRpb24gZmFpbHMgYmVjYXVzZSB0aGVyZSB3ZXJlIHNvIG1hbnkgbW9yZSBwYXJhbWV0ZXJzIHdpdGgKIycgaGllcmFyY2hpY2FsIHByaW9yLiBBcyBldmVuIHRoZSBzaG9ydCBjaGFpbiBzYW1wbGluZyB3b3VsZCBoYXZlCiMnIHRha2VuIG1vcmUgdGhhbiBob3VyLCBpdCB3b3VsZCBoYXZlIGJlZW4gdGltZSBjb25zdW1pbmcgdG8gZnVydGhlcgojJyB0byB0ZXN0IHRoZSBtb2RlbC4gQXMgcGFydCBvZiB0aGUgcXVpY2sgaXRlcmF0aXZlIG1vZGVsIGJ1aWxkaW5nIGl0CiMnIHdhcyBiZXR0ZXIgdG8gZ2l2ZSB1cCBvbiB0aGlzIG1vZGVsIGZvciBhIG1vbWVudC4KIycKIycgQ29tcGlsZSBTdGFuIG1vZGVsIDUgW2dwYmY1LnN0YW5dKGh0dHBzOi8vZ2l0aHViLmNvbS9hdmVodGFyaS9jYXNlc3R1ZGllcy9ibG9iL21hc3Rlci9CaXJ0aGRheXMvZ3BiZjUuc3RhbikKIysgbW9kZWw1LCByZXN1bHRzPSdoaWRlJwptb2RlbDUgPC0gY21kc3Rhbl9tb2RlbChzdGFuX2ZpbGUgPSByb290KCJCaXJ0aGRheXMiLCAiZ3BiZjUuc3RhbiIpLAogICAgICAgICAgICAgICAgICAgICAgICBpbmNsdWRlX3BhdGhzID0gcm9vdCgiQmlydGhkYXlzIikpCgojJyBEYXRhIHRvIGJlIHBhc3NlZCB0byBTdGFuCnN0YW5kYXRhNSA8LSBsaXN0KHg9ZGF0YSRpZCwKICAgICAgICAgICAgICAgICAgeT1sb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApLAogICAgICAgICAgICAgICAgICBOPWxlbmd0aChkYXRhJGlkKSwKICAgICAgICAgICAgICAgICAgY19mMT0xLjUsICMgZmFjdG9yIGMgb2YgYmFzaXMgZnVuY3Rpb25zIGZvciBHUCBmb3IgZjEKICAgICAgICAgICAgICAgICAgTV9mMT0xMCwgICMgbnVtYmVyIG9mIGJhc2lzIGZ1bmN0aW9ucyBmb3IgR1AgZm9yIGYxCiAgICAgICAgICAgICAgICAgIEpfZjI9MjAsICAjIG51bWJlciBvZiBiYXNpcyBmdW5jdGlvbnMgZm9yIHBlcmlvZGljIGYyCiAgICAgICAgICAgICAgICAgIGNfZzM9MS41LCAjIGZhY3RvciBjIG9mIGJhc2lzIGZ1bmN0aW9ucyBmb3IgR1AgZm9yIGczCiAgICAgICAgICAgICAgICAgIE1fZzM9NSwgICAjIG51bWJlciBvZiBiYXNpcyBmdW5jdGlvbnMgZm9yIEdQIGZvciBnMwogICAgICAgICAgICAgICAgICBzY2FsZV9nbG9iYWw9MC4xLCAjIGdsb3ZhbCBzY2FsZSBmb3IgUkhTIHByaW9yCiAgICAgICAgICAgICAgICAgIGRheV9vZl93ZWVrPWRhdGEkZGF5X29mX3dlZWssCiAgICAgICAgICAgICAgICAgIGRheV9vZl95ZWFyPWRhdGEkZGF5X29mX3llYXIyKSAjIDFzdCBNYXJjaCA9IDYxIGV2ZXJ5IHllYXIKCiMnIE9wdGltaXppbmcgaXMgZmFzdGVyIHRoYW4gc2FtcGxpbmcgKGFsdGhvdWdoIHRoaXMgcmVzdWx0IGNhbiBiZQojJyB1c2VmdWwgaW4gYSBxdWljayB3b3JrZmxvdywgdGhlIHJlc3VsdCBzaG91bGQgbm90IGJlIHVzZWQgYXMgdGhlCiMnIGZpbmFsIHJlc3VsdCkuCiMrIG9wdDUsIHJlc3VsdHM9J2hpZGUnCm9wdDUgPC0gbW9kZWw1JG9wdGltaXplKGRhdGE9c3RhbmRhdGE1LCBpbml0PTAsIGFsZ29yaXRobT0nbGJmZ3MnLAogICAgICAgICAgICAgICAgICAgICAgICBoaXN0b3J5PTEwMCwgdG9sX29iaj0xMCkKCiMnIENoZWNrIHdoZXRoZXIgcGFyYW1ldGVycyBoYXZlIHJlYXNvbmFibGUgdmFsdWVzCm9kcmF3czUgPC0gb3B0NSRkcmF3cygpCnN1YnNldChvZHJhd3M1LCB2YXJpYWJsZT1jKCdpbnRlcmNlcHQwJywnc2lnbWFfJywnbGVuZ3Roc2NhbGVfJywnc2lnbWEnKSwgcmVnZXg9VFJVRSkKc3Vic2V0KG9kcmF3czUsIHZhcmlhYmxlPWMoJ2JldGFfZjMnKSkKRWY0IDwtIGFzLm51bWVyaWMoc3Vic2V0KG9kcmF3czUsIHZhcmlhYmxlPSdiZXRhX2Y0JykpKnNkKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpCkVmNCA8LSBleHAoRWY0KSoxMDAKZGF0YS5mcmFtZSh4PWFzLkRhdGUoIjE5ODgtMDEtMDEiKSswOjM2NSwgeT1FZjQpICU+JQogIGdncGxvdChhZXMoeD14LHk9eSkpICsgZ2VvbV9saW5lKGNvbG9yPXNldDFbMV0pICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgb2YgeWVhciIpCgojJyBDb21wYXJlIHRoZSBtb2RlbCB0byB0aGUgZGF0YQpFZiA8LSBleHAoYXMubnVtZXJpYyhzdWJzZXQob2RyYXdzNSwgdmFyaWFibGU9J2YnKSkpCkVmMSA8LSBhcy5udW1lcmljKHN1YnNldChvZHJhd3M1LCB2YXJpYWJsZT0nZjEnKSkKRWYxIDwtIGV4cChFZjEgLSBtZWFuKEVmMSkgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZjIgPC0gYXMubnVtZXJpYyhzdWJzZXQob2RyYXdzNSwgdmFyaWFibGU9J2YyJykpCkVmMiA8LSBleHAoRWYyIC0gbWVhbihFZjIpICsgbWVhbihsb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApKSkKRWZfZGF5X29mX3dlZWsgPC0gYXMubnVtZXJpYyhzdWJzZXQob2RyYXdzNSwgdmFyaWFibGU9J2ZfZGF5X29mX3dlZWsnKSkKRWZfZGF5X29mX3dlZWsgPC0gZXhwKEVmX2RheV9vZl93ZWVrIC0gbWVhbihFZl9kYXlfb2Zfd2VlaykgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZjQgPC0gYXMubnVtZXJpYyhzdWJzZXQob2RyYXdzNSwgdmFyaWFibGU9J2JldGFfZjQnKSkqc2QobG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkKRWY0IDwtIGV4cChFZjQpKjEwMApwZiA8LSBkYXRhICU+JQogIG11dGF0ZShFZiA9IEVmKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9saW5lKGFlcyh5PUVmKSwgY29sb3I9c2V0MVsxXSwgYWxwaGE9MC43NSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMiKQpwZjEgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYxID0gRWYxKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9saW5lKGFlcyh5PUVmMSksIGNvbG9yPXNldDFbMV0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIikKcGYyIDwtIGRhdGEgJT4lCiAgbXV0YXRlKEVmMiA9IEVmMikgJT4lCiAgZ3JvdXBfYnkoZGF5X29mX3llYXIyKSAlPiUKICBzdW1tYXJpc2UobWVhbmJpcnRocz1tZWFuKGJpcnRoc19yZWxhdGl2ZTEwMCksIG1lYW5FZjI9bWVhbihFZjIpKSAlPiUKICBnZ3Bsb3QoYWVzKHg9YXMuRGF0ZSgiMTk4Ny0xMi0zMSIpK2RheV9vZl95ZWFyMiwgeT1tZWFuYmlydGhzKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKSArCiAgZ2VvbV9saW5lKGFlcyh5PW1lYW5FZjIpLCBjb2xvcj1zZXQxWzFdKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyBvZiB5ZWFyIikKcGYzIDwtIGdncGxvdChkYXRhPWRhdGEsIGFlcyh4PWRheV9vZl93ZWVrLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gMTo3LCBsYWJlbHM9YygnTW9uJywnVHVlJywnV2VkJywnVGh1JywnRnJpJywnU2F0JywnU3VuJykpICsKICBnZW9tX2xpbmUoZGF0YT1kYXRhLmZyYW1lKHg9MTo3LHk9RWZfZGF5X29mX3dlZWspLCBhZXMoeD14LCB5PUVmX2RheV9vZl93ZWVrKSwgY29sb3I9c2V0MVsxXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgb2Ygd2VlayIpCnBmMmIgPC1kYXRhLmZyYW1lKHg9YXMuRGF0ZSgiMTk1OS0xMi0zMSIpKzE6MzY2LCB5PUVmNCkgJT4lCiAgZ2dwbG90KGFlcyh4PXgseT15KSkgKyBnZW9tX2xpbmUoY29sb3I9c2V0MVsxXSkgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyBvZiB5ZWFyIikKKHBmICsgcGYxKSAvIChwZjIgKyBwZjMpIC8gKHBmMmIpCgojJyBUaGUgcXVpY2sgbW9kZWwgZml0IGZvciBtb2RlbCA1IGlzIG5vdCBnb29kLCBidXQgYXMgdGhlIHNhbXBsaW5nCiMnIHdhcyB2ZXJ5IHNsb3cgaXQgd2Fzbid0IGVhc3kgdG8gZmlndXJlIG91dCB3aGF0IGlzIGdvaW5nIHdyb25nLgojJyAKCiMnICMjIyBNb2RlbCA2OiBsb25nIHRlcm0gc21vb3RoICsgc2Vhc29uYWwgKyB3ZWVrZGF5ICsgZGF5IG9mIHllYXIKIycKIycgVG8gc2ltcGxpZnkgdGhlIGFuYWx5c2lzIG9mIHRoZSBkYXkgb2YgeWVhciBlZmZlY3QgYW5kIG1ha2UgdGhlCiMnIGluZmVyZW5jZSBkdXJpbmcgdGhlIGV4cGxvcmF0aW9uIGZhc3Rlciwgd2UgZHJvcCB0aGUgdGltZSBkZXBlbmRlbnQKIycgZGF5IG9mIHdlZWsgZWZmZWN0IGFuZCBSSFMgZm9yIGEgbW9tZW50IGFuZCB1c2Ugbm9ybWFsIHByaW9yIGZvcgojJyB0aGUgZGF5IG9mIHllYXIgZWZmZWN0LgojJwojJyAkJAojJyBmID0gXG1ib3h7aW50ZXJjZXB0fSArIGZfMSArIGZfMiArIFxiZXRhX3tcbWJveHtkYXkgb2Ygd2Vla319ICsgXGJldGFfe1xtYm94e2RheSBvZiB5ZWFyfX1cXAojJyBcbWJveHtpbnRlcmNlcHR9IFxzaW0gXG1ib3h7bm9ybWFsfSgwLDEpXFwKIycgZl8xIFxzaW0gXG1ib3h7R1B9KDAsS18xKVxcCiMnIGZfMiBcc2ltIFxtYm94e0dQfSgwLEtfMilcXAojJyBnXzMgXHNpbSBcbWJveHtHUH0oMCxLXzMpXFwKIycgXGJldGFfe1xtYm94e2RheSBvZiB3ZWVrfX0gPSAwIFxxdWFkIFxtYm94e2lmIGRheSBvZiB3ZWVrIGlzIE1vbmRheX1cXAojJyBcYmV0YV97XG1ib3h7ZGF5IG9mIHdlZWt9fSBcc2ltIFxtYm94e25vcm1hbH0oMCwxKSBccXVhZCBcbWJveHtpZiBkYXkgb2Ygd2VlayBpcyBub3QgTW9uZGF5fVxcCiMnIFxiZXRhX3tcbWJveHtkYXkgb2YgeWVhcn19IFxzaW0gXG1ib3h7bm9ybWFsfSgwLDAuMSkKIycgJCQKIycgCiMnIENvbXBpbGUgU3RhbiBtb2RlbCA2IFtncGJmNi5zdGFuXShodHRwczovL2dpdGh1Yi5jb20vYXZlaHRhcmkvY2FzZXN0dWRpZXMvYmxvYi9tYXN0ZXIvQmlydGhkYXlzL2dwYmY2LnN0YW4pCiMrIG1vZGVsNiwgcmVzdWx0cz0naGlkZScKbW9kZWw2IDwtIGNtZHN0YW5fbW9kZWwoc3Rhbl9maWxlID0gcm9vdCgiQmlydGhkYXlzIiwgImdwYmY2LnN0YW4iKSwKICAgICAgICAgICAgICAgICAgICAgICAgaW5jbHVkZV9wYXRocyA9IHJvb3QoIkJpcnRoZGF5cyIpKQoKIycgRGF0YSB0byBiZSBwYXNzZWQgdG8gU3RhbgpzdGFuZGF0YTYgPC0gbGlzdCh4PWRhdGEkaWQsCiAgICAgICAgICAgICAgICAgIHk9bG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSwKICAgICAgICAgICAgICAgICAgTj1sZW5ndGgoZGF0YSRpZCksCiAgICAgICAgICAgICAgICAgIGNfZjE9MS41LCAjIGZhY3RvciBjIG9mIGJhc2lzIGZ1bmN0aW9ucyBmb3IgR1AgZm9yIGYxCiAgICAgICAgICAgICAgICAgIE1fZjE9MTAsICMgbnVtYmVyIG9mIGJhc2lzIGZ1bmN0aW9ucyBmb3IgR1AgZm9yIGYxCiAgICAgICAgICAgICAgICAgIEpfZjI9MjAsICMgbnVtYmVyIG9mIGJhc2lzIGZ1bmN0aW9ucyBmb3IgcGVyaW9kaWMgZjIKICAgICAgICAgICAgICAgICAgZGF5X29mX3dlZWs9ZGF0YSRkYXlfb2Zfd2VlaywKICAgICAgICAgICAgICAgICAgZGF5X29mX3llYXI9ZGF0YSRkYXlfb2ZfeWVhcjIpICMgMXN0IE1hcmNoID0gNjEgZXZlcnkgeWVhcgoKIycgT3B0aW1pemluZyBpcyBmYXN0ZXIgdGhhbiBzYW1wbGluZyAoYWx0aG91Z2ggdGhpcyByZXN1bHQgY2FuIGJlCiMnIHVzZWZ1bCBpbiBhIHF1aWNrIHdvcmtmbG93LCB0aGUgcmVzdWx0IHNob3VsZCBub3QgYmUgdXNlZCBhcyB0aGUKIycgZmluYWwgcmVzdWx0KS4KIysgb3B0NiwgcmVzdWx0cz0naGlkZScKb3B0NiA8LSBtb2RlbDYkb3B0aW1pemUoZGF0YT1zdGFuZGF0YTYsIGluaXQ9MCwgYWxnb3JpdGhtPSdsYmZncycsCiAgICAgICAgICAgICAgICAgICAgICAgIGhpc3Rvcnk9MTAwLCB0b2xfb2JqPTEwKQoKIycgQ2hlY2sgd2hldGhlciBwYXJhbWV0ZXJzIGhhdmUgcmVhc29uYWJsZSB2YWx1ZXMKb2RyYXdzNiA8LSBvcHQ2JGRyYXdzKCkKc3Vic2V0KG9kcmF3czYsIHZhcmlhYmxlPWMoJ2ludGVyY2VwdCcsJ3NpZ21hXycsJ2xlbmd0aHNjYWxlXycsJ3NpZ21hJyksIHJlZ2V4PVRSVUUpCnN1YnNldChvZHJhd3M2LCB2YXJpYWJsZT1jKCdiZXRhX2YzJykpCkVmNCA8LSBhcy5udW1lcmljKHN1YnNldChvZHJhd3M2LCB2YXJpYWJsZT0nYmV0YV9mNCcpKSpzZChsb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApKQpFZjQgPC0gZXhwKEVmNCkqMTAwCmRhdGEuZnJhbWUoeD1hcy5EYXRlKCIxOTg4LTAxLTAxIikrMDozNjUsIHk9RWY0KSAlPiUKICBnZ3Bsb3QoYWVzKHg9eCx5PXkpKSArIGdlb21fbGluZShjb2xvcj1zZXQxWzFdKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCBkYXRlX2xhYmVscyA9ICIlYiIpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIG9mIHllYXIiKQojJyBXZSByZWNvZ25pemUgc29tZSBmYW1pbGlhciBzdHJ1Y3R1cmUgaW4gdGhlIGRheSBvZiB5ZWFyIGVmZmVjdCBhbmQKIycgcHJvY2VlZCB0byBzYW1wbGluZy4KCiMnIFNhbXBsZSBzaG9ydCBjaGFpbnMgdXNpbmcgdGhlIGVhcmx5IHN0b3BwZWQgb3B0aW1pemF0aW9uIHJlc3VsdCBhcwojJyBpbml0aWFsIHZhbHVlcyAoYWx0aG91Z2ggdGhlIHJlc3VsdCBmcm9tIHNob3J0IGNoYWlucyBjYW4gYmUgdXNlZnVsCiMnIGluIGEgcXVpY2sgd29ya2Zsb3csIHRoZSByZXN1bHQgc2hvdWxkIG5vdCBiZSB1c2VkIGFzIHRoZSBmaW5hbAojJyByZXN1bHQpLgppbml0NiA8LSBzYXBwbHkoYygnaW50ZXJjZXB0MCcsJ2xlbmd0aHNjYWxlX2YxJywnbGVuZ3Roc2NhbGVfZjInLAogICAgICAgICAgICAgICAgICAnc2lnbWFfZjEnLCdzaWdtYV9mMicsJ3NpZ21hX2Y0Jywnc2lnbWEnLAogICAgICAgICAgICAgICAgICAnYmV0YV9mMScsJ2JldGFfZjInLCdiZXRhX2YzJywnYmV0YV9mNCcpLAogICAgICAgICAgICAgICAgZnVuY3Rpb24odmFyaWFibGUpIHthcy5udW1lcmljKHN1YnNldChvZHJhd3M2LCB2YXJpYWJsZT12YXJpYWJsZSkpfSkKIysgZml0NiwgcmVzdWx0cz0naGlkZScKZml0NiA8LSBtb2RlbDYkc2FtcGxlKGRhdGE9c3RhbmRhdGE2LCBpdGVyX3dhcm11cD0xMDAsIGl0ZXJfc2FtcGxpbmc9MTAwLAogICAgICAgICAgICAgICAgICAgICAgY2hhaW5zPTQsIHBhcmFsbGVsX2NoYWlucz00LAogICAgICAgICAgICAgICAgICAgICAgaW5pdD1mdW5jdGlvbigpIHsgaW5pdDYgfSkKCiMnIENoZWNrIHdoZXRoZXIgcGFyYW1ldGVycyBoYXZlIHJlYXNvbmFibGUgdmFsdWVzCmRyYXdzNiA8LSBmaXQ2JGRyYXdzKCkKc3VtbWFyaXNlX2RyYXdzKHN1YnNldChkcmF3czYsIHZhcmlhYmxlPWMoJ2ludGVyY2VwdCcsJ3NpZ21hXycsJ2xlbmd0aHNjYWxlXycsJ3NpZ21hJyksIHJlZ2V4PVRSVUUpKQpzdW1tYXJpc2VfZHJhd3Moc3Vic2V0KGRyYXdzNiwgdmFyaWFibGU9YygnYmV0YV9mMycpKSkKZHJhd3M2IDwtIGFzX2RyYXdzX21hdHJpeChkcmF3czYpCkVmNCA8LSBhcHBseShzdWJzZXQoZHJhd3M2LCB2YXJpYWJsZT0nYmV0YV9mNCcpLCAyLCBtZWRpYW4pKnNkKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpCkVmNCA8LSBleHAoRWY0KSoxMDAKZGF0YS5mcmFtZSh4PWFzLkRhdGUoIjE5ODgtMDEtMDEiKSswOjM2NSwgeT1FZjQpICU+JQogIGdncGxvdChhZXMoeD14LHk9eSkpICsgZ2VvbV9saW5lKGNvbG9yPXNldDFbMV0pICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgb2YgeWVhciIpCgojJyBDb21wYXJlIHRoZSBtb2RlbCB0byB0aGUgZGF0YQpkcmF3czYgPC0gYXNfZHJhd3NfbWF0cml4KGRyYXdzNikKRWYgPC0gZXhwKGFwcGx5KHN1YnNldChkcmF3czYsIHZhcmlhYmxlPSdmJyksIDIsIG1lZGlhbikpCkVmMSA8LSBhcHBseShzdWJzZXQoZHJhd3M2LCB2YXJpYWJsZT0nZjEnKSwgMiwgbWVkaWFuKQpFZjEgPC0gZXhwKEVmMSAtIG1lYW4oRWYxKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCkVmMiA8LSBhcHBseShzdWJzZXQoZHJhd3M2LCB2YXJpYWJsZT0nZjInKSwgMiwgbWVkaWFuKQpFZjIgPC0gZXhwKEVmMiAtIG1lYW4oRWYyKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCkVmX2RheV9vZl93ZWVrIDwtIGFwcGx5KHN1YnNldChkcmF3czYsIHZhcmlhYmxlPSdmX2RheV9vZl93ZWVrJyksIDIsIG1lZGlhbikKRWZfZGF5X29mX3dlZWsgPC0gZXhwKEVmX2RheV9vZl93ZWVrIC0gbWVhbihFZl9kYXlfb2Zfd2VlaykgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZjQgPC0gYXBwbHkoc3Vic2V0KGRyYXdzNiwgdmFyaWFibGU9J2JldGFfZjQnKSwgMiwgbWVkaWFuKSpzZChsb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApKQpFZjQgPC0gZXhwKEVmNCkqMTAwCnBmIDwtIGRhdGEgJT4lCiAgbXV0YXRlKEVmID0gRWYpICU+JQogIGdncGxvdChhZXMoeD1kYXRlLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBnZW9tX2xpbmUoYWVzKHk9RWYpLCBjb2xvcj1zZXQxWzFdLCBhbHBoYT0wLjc1KSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyIpCnBmMSA8LSBkYXRhICU+JQogIG11dGF0ZShFZjEgPSBFZjEpICU+JQogIGdncGxvdChhZXMoeD1kYXRlLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBnZW9tX2xpbmUoYWVzKHk9RWYxKSwgY29sb3I9c2V0MVsxXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMiKQpwZjIgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYyID0gRWYyKSAlPiUKICBncm91cF9ieShkYXlfb2ZfeWVhcjIpICU+JQogIHN1bW1hcmlzZShtZWFuYmlydGhzPW1lYW4oYmlydGhzX3JlbGF0aXZlMTAwKSwgbWVhbkVmMj1tZWFuKEVmMikpICU+JQogIGdncGxvdChhZXMoeD1hcy5EYXRlKCIxOTg3LTEyLTMxIikrZGF5X29mX3llYXIyLCB5PW1lYW5iaXJ0aHMpKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCBkYXRlX2xhYmVscyA9ICIlYiIpICsKICBnZW9tX2xpbmUoYWVzKHk9bWVhbkVmMiksIGNvbG9yPXNldDFbMV0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIG9mIHllYXIiKQpwZjMgPC0gZ2dwbG90KGRhdGE9ZGF0YSwgYWVzKHg9ZGF5X29mX3dlZWssIHk9YmlydGhzX3JlbGF0aXZlMTAwKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSAxOjcsIGxhYmVscz1jKCdNb24nLCdUdWUnLCdXZWQnLCdUaHUnLCdGcmknLCdTYXQnLCdTdW4nKSkgKwogIGdlb21fbGluZShkYXRhPWRhdGEuZnJhbWUoeD0xOjcseT1FZl9kYXlfb2Zfd2VlayksIGFlcyh4PXgsIHk9RWZfZGF5X29mX3dlZWspLCBjb2xvcj1zZXQxWzFdKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyBvZiB3ZWVrIikKZjEzIDwtIGRhdGEgJT4lIGZpbHRlcih5ZWFyPT0xOTg4KSU+JXNlbGVjdChkYXksZGF0ZSklPiVtdXRhdGUoeT1FZjQpJT4lZmlsdGVyKGRheT09MTMpCnBmMmIgPC1kYXRhLmZyYW1lKHg9YXMuRGF0ZSgiMTk4OC0wMS0wMSIpKzA6MzY1LCB5PUVmNCkgJT4lCiAgZ2dwbG90KGFlcyh4PXgseT15KSkgKyBnZW9tX2xpbmUoY29sb3I9c2V0MVsxXSkgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyBvZiB5ZWFyIikgKwogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMDEtMDEiKSx5PUVmNFsxXS0xLGxhYmVsPSJOZXcgeWVhciIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTAyLTE0IikseT1FZjRbNDVdKzEuNSxsYWJlbD0iVmFsZW50aW5lJ3MgZGF5IikgKwogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMDItMjkiKSx5PUVmNFs2MF0tMi41LGxhYmVsPSJMZWFwIGRheSIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTA0LTAxIikseT1FZjRbOTJdLTEuNSxsYWJlbD0iQXByaWwgMXN0IikgKyAKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTA3LTA0IikseT1FZjRbMTg2XS0xLjUsbGFiZWw9IkluZGVwZW5kZW5jZSBkYXkiKSArCiAgYW5ub3RhdGUoInRleHQiLHg9YXMuRGF0ZSgiMTk4OC0xMC0zMSIpLHk9RWY0WzMwNV0tMS41LGxhYmVsPSJIYWxsb3dlZW4iKSArIAogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMTItMjQiKSx5PUVmNFszNjBdLTEuNSxsYWJlbD0iQ2hyaXN0bWFzIikgKwogIGdlb21fcG9pbnQoZGF0YT1mMTMsYWVzKHg9ZGF0ZSx5PXkpLCBzaXplPTMsIHNoYXBlPTEpCihwZiArIHBmMSkgLyAocGYyICsgcGYzKSAvIHBmMmIKCiMnIFRoZSBzaG9ydCBzYW1wbGluZyByZXN1bHQgbG9va3MgcmVhc29uYWJsZSBhbmQgdGh1cyB0aGUgcHJvYmxlbSBpcwojJyBub3QgaW4gYWRkaW5nIHRoZSBkYXkgb2YgeWVhciBlZmZlY3QgaXRzZWxmLiAgSW4gdGhlIGJvdHRvbSBwbG90LAojJyB0aGUgY2lyY2xlcyBtYXJrIDEzdGggZGF5IG9mIGVhY2ggbW9udGguIFJlc3VsdHMgbG9vayBzaW1pbGFyIHRvCiMnIG91ciBwcmV2aW91cyBhbmFseXNlcyAsIHNvIGl0IHNlZW1zIHRoZSBkYXkgb3IgeWVhciBlZmZlY3QgbW9kZWwKIycgY29tcG9uZW50IGlzIHdvcmtpbmcgYXMgaXQgc2hvdWxkLCBidXQgdGhlcmUgd2FzIHNvbWUgcHJvYmxlbSB3aXRoCiMnIG91ciBSSFMgaW1wbGVtZW50YXRpb24uIEFzIHRoZXJlIGlzIG1vcmUgdmFyaWF0aW9uIGluIHRoZSBkYXkgb2YKIycgeWVhciBlZmZlY3RzIHRoYW4gd2Ugd291bGQgaG9wZSwgd2UgZGlkIHNvbWUgYWRkaXRpb25hbCBleHBlcmltZW50cwojJyB3aXRoIGRpZmZlcmVudCBwcmlvcnMgZm9yIHRoZSBkYXkgb2YgeWVhciBlZmZlY3QgKGRvdWJsZQojJyBleHBvbmVudGlhbCwgQ2F1Y2h5IGFuZCBTdHVkZW50J3MgdCB3aXRoIHVua25vd24gZGVncmVlcyBvZiBmcmVlZG9tCiMnIGFzIG1vZGVscyA2YiwgNmMsIDZkKSwgYnV0IGRlY2lkZWQgaXQncyBiZXR0ZXIgdG8gYWRkIG90aGVyCiMnIGNvbXBvbmVudHMgYmVmb3JlIGludmVzdGluZyB0aGF0IHBhcnQgbW9yZSB0aG9yb3VnaGx5LgojJyAKCiMnICMjIyBNb2RlbCA3OiBsb25nIHRlcm0gc21vb3RoICsgc2Vhc29uYWwgKyB3ZWVrZGF5ICsgZGF5IG9mIHllYXIgbm9ybWFsICsgZmxvYXRpbmcgc3BlY2lhbCBkYXlzCiMnCiMnIFdlIGNhbiBzZWUgaW4gdGhlIG1vZGVsIDYgcmVzdWx0cyB0aGF0IGRheSBvZiB5ZWFyIGVmZmVjdHMgaGF2ZQojJyBzb21lIGRpcHMgaW4gdGhlIHJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgdGhhdCBhcmUgc3ByZWFkIG92ZXIgYQojJyB3ZWVrLiBGcm9tIHByZXZpb3VzIGFuYWx5c2Ugd2Uga25vdyB0aGVzZSBjb3JyZXNwb25kIHRvIGhvbGlkYXlzCiMnIHRoYXQgYXJlIG5vdCBvbiBhIHNwZWNpZmljIGRheSBvZiB5ZWFyLCBidXQgYXJlIGZvciBleGFtcGxlIG9uIHRoZQojJyBsYXN0IE1vbmRheSBvZiBNYXkuIFdlIGNhbGwgdGhlc2UgZmxvYXRpbmcgc3BlY2lhbCBkYXlzIGFuZCBpbmNsdWRlCiMnIE1lbW9yaWFsIGRheSAobGFzdCBNb25kYXkgb2YgTWF5KSwgTGFib3IgZGF5IChmaXJzdCBNb25kYXkgb2YKIycgU2VwdGVtYmVyLCBhbmQgd2UgaW5jbHVkZSBhbHNvIHRoZSBmb2xsb3dpbmcgVHVlc2RheSksIGFuZAojJyBUaGFua3NnaXZpbmcgKGZvdXJ0aCBUaHVyc2RheSBvZiBOb3ZlbWJlciwgYW5kIHdlIGluY2x1ZGUgYWxzbyB0aGUKIycgZm9sbG93aW5nIEZyaWRheSkuCiMnCiMnIENvbXBpbGUgU3RhbiBtb2RlbCA3IFtncGJmNy5zdGFuXShodHRwczovL2dpdGh1Yi5jb20vYXZlaHRhcmkvY2FzZXN0dWRpZXMvYmxvYi9tYXN0ZXIvQmlydGhkYXlzL2dwYmY3LnN0YW4pCiMrIG1vZGVsNywgcmVzdWx0cz0naGlkZScKbW9kZWw3IDwtIGNtZHN0YW5fbW9kZWwoc3Rhbl9maWxlID0gcm9vdCgiQmlydGhkYXlzIiwgImdwYmY3LnN0YW4iKSwKICAgICAgICAgICAgICAgICAgICAgICAgaW5jbHVkZV9wYXRocyA9IHJvb3QoIkJpcnRoZGF5cyIpKQoKIycgRmxvYXRpbmcgc3BlY2lhbCBkYXlzCiMgTWVtb3JpYWwgZGF5Cm1lbW9yaWFsX2RheXMgPC0gd2l0aChkYXRhLHdoaWNoKG1vbnRoPT01JmRheV9vZl93ZWVrPT0xJmRheT49MjUpKQojIExhYm9yIGRheQpsYWJvcl9kYXlzIDwtIHdpdGgoZGF0YSx3aGljaChtb250aD09OSZkYXlfb2Zfd2Vlaz09MSZkYXk8PTcpKQpsYWJvcl9kYXlzIDwtIGMobGFib3JfZGF5cywgbGFib3JfZGF5cysxKQojIFRoYW5rc2dpdmluZwp0aGFua3NnaXZpbmdfZGF5cyA8LSB3aXRoKGRhdGEsd2hpY2gobW9udGg9PTExJmRheV9vZl93ZWVrPT00JmRheT49MjImZGF5PD0yOCkpCnRoYW5rc2dpdmluZ19kYXlzIDwtIGModGhhbmtzZ2l2aW5nX2RheXMsIHRoYW5rc2dpdmluZ19kYXlzKzEpCgojJyBEYXRhIHRvIGJlIHBhc3NlZCB0byBTdGFuCnN0YW5kYXRhNyA8LSBsaXN0KHg9ZGF0YSRpZCwKICAgICAgICAgICAgICAgICAgeT1sb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApLAogICAgICAgICAgICAgICAgICBOPWxlbmd0aChkYXRhJGlkKSwKICAgICAgICAgICAgICAgICAgY19mMT0xLjUsICMgZmFjdG9yIGMgb2YgYmFzaXMgZnVuY3Rpb25zIGZvciBHUCBmb3IgZjEKICAgICAgICAgICAgICAgICAgTV9mMT0xMCwgICMgbnVtYmVyIG9mIGJhc2lzIGZ1bmN0aW9ucyBmb3IgR1AgZm9yIGYxCiAgICAgICAgICAgICAgICAgIEpfZjI9MjAsICAjIG51bWJlciBvZiBiYXNpcyBmdW5jdGlvbnMgZm9yIHBlcmlvZGljIGYyCiAgICAgICAgICAgICAgICAgIGRheV9vZl93ZWVrPWRhdGEkZGF5X29mX3dlZWssCiAgICAgICAgICAgICAgICAgIGRheV9vZl95ZWFyPWRhdGEkZGF5X29mX3llYXIyLCAjIDFzdCBNYXJjaCA9IDYxIGV2ZXJ5IHllYXIKICAgICAgICAgICAgICAgICAgbWVtb3JpYWxfZGF5cz1tZW1vcmlhbF9kYXlzLAogICAgICAgICAgICAgICAgICBsYWJvcl9kYXlzPWxhYm9yX2RheXMsCiAgICAgICAgICAgICAgICAgIHRoYW5rc2dpdmluZ19kYXlzPXRoYW5rc2dpdmluZ19kYXlzKQoKIycgT3B0aW1pemluZyBpcyBmYXN0ZXIgdGhhbiBzYW1wbGluZyAoYWx0aG91Z2ggdGhpcyByZXN1bHQgY2FuIGJlCiMnIHVzZWZ1bCBpbiBhIHF1aWNrIHdvcmtmbG93LCB0aGUgcmVzdWx0IHNob3VsZCBub3QgYmUgdXNlZCBhcyB0aGUKIycgZmluYWwgcmVzdWx0KS4KIysgb3B0NywgcmVzdWx0cz0naGlkZScKb3B0NyA8LSBtb2RlbDckb3B0aW1pemUoZGF0YT1zdGFuZGF0YTcsIGluaXQ9MCwgYWxnb3JpdGhtPSdsYmZncycsCiAgICAgICAgICAgICAgICAgICAgICAgIGhpc3Rvcnk9MTAwLCB0b2xfb2JqPTEwKQoKIycgQ2hlY2sgd2hldGhlciBwYXJhbWV0ZXJzIGhhdmUgcmVhc29uYWJsZSB2YWx1ZXMKb2RyYXdzNyA8LSBvcHQ3JGRyYXdzKCkKc3Vic2V0KG9kcmF3czcsIHZhcmlhYmxlPWMoJ2ludGVyY2VwdCcsJ3NpZ21hXycsJ2xlbmd0aHNjYWxlXycsJ3NpZ21hJyksIHJlZ2V4PVRSVUUpCnN1YnNldChvZHJhd3M3LCB2YXJpYWJsZT1jKCdiZXRhX2YzJykpCkVmNCA8LSBhcy5udW1lcmljKHN1YnNldChvZHJhd3M3LCB2YXJpYWJsZT0nYmV0YV9mNCcpKSpzZChsb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApKQpFZjQgPC0gZXhwKEVmNCkqMTAwCmRhdGEuZnJhbWUoeD1hcy5EYXRlKCIxOTg4LTAxLTAxIikrMDozNjUsIHk9RWY0KSAlPiUKICBnZ3Bsb3QoYWVzKHg9eCx5PXkpKSArIGdlb21fbGluZShjb2xvcj1zZXQxWzFdKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCBkYXRlX2xhYmVscyA9ICIlYiIpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIG9mIHllYXIiKQoKIycgU2FtcGxlIHNob3J0IGNoYWlucyB1c2luZyB0aGUgZWFybHkgc3RvcHBlZCBvcHRpbWl6YXRpb24gcmVzdWx0IGFzCiMnIGluaXRpYWwgdmFsdWVzIChhbHRob3VnaCB0aGUgcmVzdWx0IGZyb20gc2hvcnQgY2hhaW5zIGNhbiBiZSB1c2VmdWwKIycgaW4gYSBxdWljayB3b3JrZmxvdywgdGhlIHJlc3VsdCBzaG91bGQgbm90IGJlIHVzZWQgYXMgdGhlIGZpbmFsCiMnIHJlc3VsdCkuCmluaXQ3IDwtIHNhcHBseShjKCdpbnRlcmNlcHQwJywnbGVuZ3Roc2NhbGVfZjEnLCdsZW5ndGhzY2FsZV9mMicsCiAgICAgICAgICAgICAgICAgICdzaWdtYV9mMScsJ3NpZ21hX2YyJywnc2lnbWFfZjQnLCdzaWdtYScsCiAgICAgICAgICAgICAgICAgICdiZXRhX2YxJywnYmV0YV9mMicsJ2JldGFfZjMnLCdiZXRhX2Y0JywnYmV0YV9mNScpLAogICAgICAgICAgICAgICAgZnVuY3Rpb24odmFyaWFibGUpIHthcy5udW1lcmljKHN1YnNldChvZHJhd3M3LCB2YXJpYWJsZT12YXJpYWJsZSkpfSkKIysgZml0NywgcmVzdWx0cz0naGlkZScKZml0NyA8LSBtb2RlbDckc2FtcGxlKGRhdGE9c3RhbmRhdGE3LCBpdGVyX3dhcm11cD0xMDAsIGl0ZXJfc2FtcGxpbmc9MTAwLCBjaGFpbnM9NCwgcGFyYWxsZWxfY2hhaW5zPTQsCiAgICAgICAgICAgICAgICAgICAgICBpbml0PWZ1bmN0aW9uKCkgeyBpbml0NyB9LCByZWZyZXNoPTEwKQoKIycgQ2hlY2sgd2hldGhlciBwYXJhbWV0ZXJzIGhhdmUgcmVhc29uYWJsZSB2YWx1ZXMKZHJhd3M3IDwtIGZpdDckZHJhd3MoKQpzdW1tYXJpc2VfZHJhd3Moc3Vic2V0KGRyYXdzNywgdmFyaWFibGU9YygnaW50ZXJjZXB0Jywnc2lnbWFfJywnbGVuZ3Roc2NhbGVfJywnc2lnbWEnKSwgcmVnZXg9VFJVRSkpCnN1bW1hcmlzZV9kcmF3cyhzdWJzZXQoZHJhd3M3LCB2YXJpYWJsZT1jKCdiZXRhX2YzJykpKQoKIycgQ29tcGFyZSB0aGUgbW9kZWwgdG8gdGhlIGRhdGEKZHJhd3M3IDwtIGFzX2RyYXdzX21hdHJpeChkcmF3czcpCkVmIDwtIGV4cChhcHBseShzdWJzZXQoZHJhd3M3LCB2YXJpYWJsZT0nZicpLCAyLCBtZWRpYW4pKQpFZjEgPC0gYXBwbHkoc3Vic2V0KGRyYXdzNywgdmFyaWFibGU9J2YxJyksIDIsIG1lZGlhbikKRWYxIDwtIGV4cChFZjEgLSBtZWFuKEVmMSkgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZjIgPC0gYXBwbHkoc3Vic2V0KGRyYXdzNywgdmFyaWFibGU9J2YyJyksIDIsIG1lZGlhbikKRWYyIDwtIGV4cChFZjIgLSBtZWFuKEVmMikgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZl9kYXlfb2Zfd2VlayA8LSBhcHBseShzdWJzZXQoZHJhd3M3LCB2YXJpYWJsZT0nZl9kYXlfb2Zfd2VlaycpLCAyLCBtZWRpYW4pCkVmX2RheV9vZl93ZWVrIDwtIGV4cChFZl9kYXlfb2Zfd2VlayAtIG1lYW4oRWZfZGF5X29mX3dlZWspICsgbWVhbihsb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApKSkKRWY0IDwtIGFwcGx5KHN1YnNldChkcmF3czcsIHZhcmlhYmxlPSdiZXRhX2Y0JyksIDIsIG1lZGlhbikqc2QobG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkKRWY0IDwtIGV4cChFZjQpKjEwMApFZmxvYXRzIDwtIGFwcGx5KHN1YnNldChkcmF3czcsIHZhcmlhYmxlPSdiZXRhX2Y1JyksIDIsIG1lZGlhbikqc2QobG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkKRWZsb2F0cyA8LSBleHAoRWZsb2F0cykqMTAwCmZsb2F0czE5ODg8LWMobWVtb3JpYWxfZGF5c1syMF0sIGxhYm9yX2RheXNbYygyMCw0MCldLCB0aGFua3NnaXZpbmdfZGF5c1tjKDIwLDQwKV0pLTY5MzkKRWY0ZmxvYXQgPC0gRWY0CkVmNGZsb2F0W2Zsb2F0czE5ODhdIDwtIEVmNGZsb2F0W2Zsb2F0czE5ODhdKkVmbG9hdHNbYygxLDIsMiwzLDMpXS8xMDAKcGYgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYgPSBFZikgJT4lCiAgZ2dwbG90KGFlcyh4PWRhdGUsIHk9YmlydGhzX3JlbGF0aXZlMTAwKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIGdlb21fbGluZShhZXMoeT1FZiksIGNvbG9yPXNldDFbMV0sIGFscGhhPTAuNzUpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIikKcGYxIDwtIGRhdGEgJT4lCiAgbXV0YXRlKEVmMSA9IEVmMSkgJT4lCiAgZ2dwbG90KGFlcyh4PWRhdGUsIHk9YmlydGhzX3JlbGF0aXZlMTAwKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIGdlb21fbGluZShhZXMoeT1FZjEpLCBjb2xvcj1zZXQxWzFdKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyIpCnBmMiA8LSBkYXRhICU+JQogIG11dGF0ZShFZjIgPSBFZjIpICU+JQogIGdyb3VwX2J5KGRheV9vZl95ZWFyMikgJT4lCiAgc3VtbWFyaXNlKG1lYW5iaXJ0aHM9bWVhbihiaXJ0aHNfcmVsYXRpdmUxMDApLCBtZWFuRWYyPW1lYW4oRWYyKSkgJT4lCiAgZ2dwbG90KGFlcyh4PWFzLkRhdGUoIjE5ODctMTItMzEiKStkYXlfb2ZfeWVhcjIsIHk9bWVhbmJpcnRocykpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikgKwogIGdlb21fbGluZShhZXMoeT1tZWFuRWYyKSwgY29sb3I9c2V0MVsxXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgb2YgeWVhciIpCnBmMyA8LSBnZ3Bsb3QoZGF0YT1kYXRhLCBhZXMoeD1kYXlfb2Zfd2VlaywgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IDE6NywgbGFiZWxzPWMoJ01vbicsJ1R1ZScsJ1dlZCcsJ1RodScsJ0ZyaScsJ1NhdCcsJ1N1bicpKSArCiAgZ2VvbV9saW5lKGRhdGE9ZGF0YS5mcmFtZSh4PTE6Nyx5PUVmX2RheV9vZl93ZWVrKSwgYWVzKHg9eCwgeT1FZl9kYXlfb2Zfd2VlayksIGNvbG9yPXNldDFbMV0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIG9mIHdlZWsiKQpmMTMgPC0gZGF0YSAlPiUgZmlsdGVyKHllYXI9PTE5ODgpJT4lc2VsZWN0KGRheSxkYXRlKSU+JW11dGF0ZSh5PUVmNGZsb2F0KSU+JWZpbHRlcihkYXk9PTEzKQoKcGYyYiA8LWRhdGEuZnJhbWUoeD1hcy5EYXRlKCIxOTg4LTAxLTAxIikrMDozNjUsIHk9RWY0ZmxvYXQpICU+JQogIGdncGxvdChhZXMoeD14LHk9eSkpICsgZ2VvbV9saW5lKGNvbG9yPXNldDFbMV0pICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgb2YgeWVhciIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTAxLTAxIikseT1FZjRmbG9hdFsxXS0xLGxhYmVsPSJOZXcgeWVhciIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTAyLTE0IikseT1FZjRmbG9hdFs0NV0rMS41LGxhYmVsPSJWYWxlbnRpbmUncyBkYXkiKSArCiAgYW5ub3RhdGUoInRleHQiLHg9YXMuRGF0ZSgiMTk4OC0wMi0yOSIpLHk9RWY0ZmxvYXRbNjBdLTIuNSxsYWJlbD0iTGVhcCBkYXkiKSArCiAgYW5ub3RhdGUoInRleHQiLHg9YXMuRGF0ZSgiMTk4OC0wNC0wMSIpLHk9RWY0ZmxvYXRbOTJdLTEuNSxsYWJlbD0iQXByaWwgMXN0IikgKyAKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTA3LTA0IikseT1FZjRmbG9hdFsxODZdLTEuNSxsYWJlbD0iSW5kZXBlbmRlbmNlIGRheSIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTEwLTMxIikseT1FZjRmbG9hdFszMDVdLTEuNSxsYWJlbD0iSGFsbG93ZWVuIikgKyAKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTEyLTI0IikseT1FZjRmbG9hdFszNjBdLTIsbGFiZWw9IkNocmlzdG1hcyIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTA1LTMwIikseT1FZjRmbG9hdFsxNTFdLTEuNSxsYWJlbD0iTWVtb3JpYWwgZGF5IikgKwogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMDktMDUiKSx5PUVmNGZsb2F0WzI0OV0tMS41LGxhYmVsPSJMYWJvciBkYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMTEtMjQiKSx5PUVmNGZsb2F0WzMyOV0tMSxsYWJlbD0iVGhhbmtzZ2l2aW5nIikrCiAgZ2VvbV9wb2ludChkYXRhPWYxMyxhZXMoeD1kYXRlLHk9eSksIHNpemU9Mywgc2hhcGU9MSkKKHBmICsgcGYxKSAvIChwZjIgKyBwZjMpIC8gKHBmMmIpCgojJyBUaGUgZGF5IG9mIHllYXIgYW5kIGZsb2F0aW5nIHNwZWNpYWwgZGF5IGVmZmVjdHMgYXJlIHNob3duIGZvciB5ZWFyCiMnIDE5ODggKHdoaWNoIGlzIGFsc28gYSBsZWFwIHllYXIpIGFuZCB0aGUgcmVzdWx0cyBzZWVtIHJlYXNvbmFibGUuCiMnIAoKIycgIyMjIE1vZGVsIDg6IGxvbmcgdGVybSBzbW9vdGggKyBzZWFzb25hbCArIHdlZWtkYXkgd2l0aCB0aW1lIGRlcGVuZGVudCBtYWduaXR1ZGUgKyBkYXkgb2YgeWVhciArIHNwZWNpYWwKIycKIycgQXMgdGhlIGRheSBvZiB5ZWFyIGFuZCBmbG9hdGluZyBkYXkgZWZmZWN0cyB3b3JrIHdlbGwsIHdlJ2xsIGFkZAojJyB0aGUgdGltZSBkZXBlbmRlbnQgZGF5IG9mIHdlZWsgZWZmZWN0IGJhY2sgdG8gdGhlIG1vZGVsLgojJyAKIycgQ29tcGlsZSBTdGFuIG1vZGVsIDggW2dwYmY4LnN0YW5dKGh0dHBzOi8vZ2l0aHViLmNvbS9hdmVodGFyaS9jYXNlc3R1ZGllcy9ibG9iL21hc3Rlci9CaXJ0aGRheXMvZ3BiZjguc3RhbikKIysgbW9kZWw4LCByZXN1bHRzPSdoaWRlJwptb2RlbDggPC0gY21kc3Rhbl9tb2RlbChzdGFuX2ZpbGUgPSByb290KCJCaXJ0aGRheXMiLCAiZ3BiZjguc3RhbiIpLAogICAgICAgICAgICAgICAgICAgICAgICBpbmNsdWRlX3BhdGhzID0gcm9vdCgiQmlydGhkYXlzIikpCgojJyBGbG9hdGluZyBzcGVjaWFsIGRheXMKIyBNZW1vcmlhbCBkYXkKbWVtb3JpYWxfZGF5cyA8LSB3aXRoKGRhdGEsd2hpY2gobW9udGg9PTUmZGF5X29mX3dlZWs9PTEmZGF5Pj0yNSkpCiMgTGFib3IgZGF5CmxhYm9yX2RheXMgPC0gd2l0aChkYXRhLHdoaWNoKG1vbnRoPT05JmRheV9vZl93ZWVrPT0xJmRheTw9NykpCmxhYm9yX2RheXMgPC0gYyhsYWJvcl9kYXlzLCBsYWJvcl9kYXlzKzEpCiMgVGhhbmtzZ2l2aW5nCnRoYW5rc2dpdmluZ19kYXlzIDwtIHdpdGgoZGF0YSx3aGljaChtb250aD09MTEmZGF5X29mX3dlZWs9PTQmZGF5Pj0yMiZkYXk8PTI4KSkKdGhhbmtzZ2l2aW5nX2RheXMgPC0gYyh0aGFua3NnaXZpbmdfZGF5cywgdGhhbmtzZ2l2aW5nX2RheXMrMSkKCiMnIERhdGEgdG8gYmUgcGFzc2VkIHRvIFN0YW4Kc3RhbmRhdGE4IDwtIGxpc3QoeD1kYXRhJGlkLAogICAgICAgICAgICAgICAgICB5PWxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCksCiAgICAgICAgICAgICAgICAgIE49bGVuZ3RoKGRhdGEkaWQpLAogICAgICAgICAgICAgICAgICBjX2YxPTEuNSwgIyBmYWN0b3IgYyBvZiBiYXNpcyBmdW5jdGlvbnMgZm9yIEdQIGZvciBmMQogICAgICAgICAgICAgICAgICBNX2YxPTEwLCAgIyBudW1iZXIgb2YgYmFzaXMgZnVuY3Rpb25zIGZvciBHUCBmb3IgZjEKICAgICAgICAgICAgICAgICAgSl9mMj0yMCwgICMgbnVtYmVyIG9mIGJhc2lzIGZ1bmN0aW9ucyBmb3IgcGVyaW9kaWMgZjIKICAgICAgICAgICAgICAgICAgY19nMz0xLjUsICMgZmFjdG9yIGMgb2YgYmFzaXMgZnVuY3Rpb25zIGZvciBHUCBmb3IgZzMKICAgICAgICAgICAgICAgICAgTV9nMz01LCAgICMgbnVtYmVyIG9mIGJhc2lzIGZ1bmN0aW9ucyBmb3IgR1AgZm9yIGczCiAgICAgICAgICAgICAgICAgIGRheV9vZl93ZWVrPWRhdGEkZGF5X29mX3dlZWssCiAgICAgICAgICAgICAgICAgIGRheV9vZl95ZWFyPWRhdGEkZGF5X29mX3llYXIyLCAjIDFzdCBNYXJjaCA9IDYxIGV2ZXJ5IHllYXIKICAgICAgICAgICAgICAgICAgbWVtb3JpYWxfZGF5cz1tZW1vcmlhbF9kYXlzLAogICAgICAgICAgICAgICAgICBsYWJvcl9kYXlzPWxhYm9yX2RheXMsCiAgICAgICAgICAgICAgICAgIHRoYW5rc2dpdmluZ19kYXlzPXRoYW5rc2dpdmluZ19kYXlzKQoKIycgT3B0aW1pemluZyBpcyBmYXN0ZXIgdGhhbiBzYW1wbGluZyAoYWx0aG91Z2ggdGhpcyByZXN1bHQgY2FuIGJlCiMnIHVzZWZ1bCBpbiBhIHF1aWNrIHdvcmtmbG93LCB0aGUgcmVzdWx0IHNob3VsZCBub3QgYmUgdXNlZCBhcyB0aGUKIycgZmluYWwgcmVzdWx0KS4KIysgb3B0OCwgcmVzdWx0cz0naGlkZScKb3B0OCA8LSBtb2RlbDgkb3B0aW1pemUoZGF0YT1zdGFuZGF0YTgsIGluaXQ9MC4xLCBhbGdvcml0aG09J2xiZmdzJywKICAgICAgICAgICAgICAgICAgICAgICAgaGlzdG9yeT0xMDAsIHRvbF9vYmo9MTApCgojJyBDaGVjayB3aGV0aGVyIHBhcmFtZXRlcnMgaGF2ZSByZWFzb25hYmxlIHZhbHVlcwpvZHJhd3M4IDwtIG9wdDgkZHJhd3MoKQpzdWJzZXQob2RyYXdzOCwgdmFyaWFibGU9YygnaW50ZXJjZXB0Jywnc2lnbWFfJywnbGVuZ3Roc2NhbGVfJywnc2lnbWEnKSwgcmVnZXg9VFJVRSkKc3Vic2V0KG9kcmF3czgsIHZhcmlhYmxlPWMoJ2JldGFfZjMnKSkKRWY0IDwtIGFzLm51bWVyaWMoc3Vic2V0KG9kcmF3czgsIHZhcmlhYmxlPSdiZXRhX2Y0JykpKnNkKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpCkVmNCA8LSBleHAoRWY0KSoxMDAKZGF0YS5mcmFtZSh4PWFzLkRhdGUoIjE5ODgtMDEtMDEiKSswOjM2NSwgeT1FZjQpICU+JQogIGdncGxvdChhZXMoeD14LHk9eSkpICsgZ2VvbV9saW5lKGNvbG9yPXNldDFbMV0pICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgb2YgeWVhciIpCgojJyBDb21wYXJlIHRoZSBtb2RlbCB0byB0aGUgZGF0YQpFZiA8LSBleHAoYXMubnVtZXJpYyhzdWJzZXQob2RyYXdzOCwgdmFyaWFibGU9J2YnKSkpCkVmMSA8LSBhcy5udW1lcmljKHN1YnNldChvZHJhd3M4LCB2YXJpYWJsZT0nZjEnKSkKRWYxIDwtIGV4cChFZjEgLSBtZWFuKEVmMSkgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZjIgPC0gYXMubnVtZXJpYyhzdWJzZXQob2RyYXdzOCwgdmFyaWFibGU9J2YyJykpCkVmMiA8LSBleHAoRWYyIC0gbWVhbihFZjIpICsgbWVhbihsb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApKSkKRWZfZGF5X29mX3dlZWsgPC0gYXMubnVtZXJpYyhzdWJzZXQob2RyYXdzOCwgdmFyaWFibGU9J2ZfZGF5X29mX3dlZWsnKSkKRWZfZGF5X29mX3dlZWsgPC0gZXhwKEVmX2RheV9vZl93ZWVrIC0gbWVhbihFZl9kYXlfb2Zfd2VlaykgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZjMgPC0gYXMubnVtZXJpYyhzdWJzZXQob2RyYXdzOCwgdmFyaWFibGU9J2YzJykpCkVmMyA8LSBleHAoRWYzIC0gbWVhbihFZjMpICsgbWVhbihsb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApKSkKRWY0IDwtIGFzLm51bWVyaWMoc3Vic2V0KG9kcmF3czgsIHZhcmlhYmxlPSdiZXRhX2Y0JykpKnNkKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpCkVmNCA8LSBleHAoRWY0KSoxMDAKRWZsb2F0cyA8LSBhcy5udW1lcmljKHN1YnNldChvZHJhd3M4LCB2YXJpYWJsZT0nYmV0YV9mNScpKSpzZChsb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApKQpFZmxvYXRzIDwtIGV4cChFZmxvYXRzKSoxMDAKZmxvYXRzMTk4ODwtYyhtZW1vcmlhbF9kYXlzWzIwXSwgbGFib3JfZGF5c1tjKDIwLDQwKV0sIHRoYW5rc2dpdmluZ19kYXlzW2MoMjAsNDApXSktNjkzOQpFZjRmbG9hdCA8LSBFZjQKRWY0ZmxvYXRbZmxvYXRzMTk4OF0gPC0gRWY0ZmxvYXRbZmxvYXRzMTk4OF0qRWZsb2F0c1tjKDEsMiwyLDMsMyldLzEwMApwZiA8LSBkYXRhICU+JQogIG11dGF0ZShFZiA9IEVmKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9wb2ludChhZXMoeT1FZiksIGNvbG9yPXNldDFbMV0sIGFscGhhPTAuMikgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMiKQpwZjEgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYxID0gRWYxKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9saW5lKGFlcyh5PUVmMSksIGNvbG9yPXNldDFbMV0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIikKcGYyIDwtIGRhdGEgJT4lCiAgbXV0YXRlKEVmMiA9IEVmMikgJT4lCiAgZ3JvdXBfYnkoZGF5X29mX3llYXIyKSAlPiUKICBzdW1tYXJpc2UobWVhbmJpcnRocz1tZWFuKGJpcnRoc19yZWxhdGl2ZTEwMCksIG1lYW5FZjI9bWVhbihFZjIpKSAlPiUKICBnZ3Bsb3QoYWVzKHg9YXMuRGF0ZSgiMTk4Ny0xMi0zMSIpK2RheV9vZl95ZWFyMiwgeT1tZWFuYmlydGhzKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKSArCiAgZ2VvbV9saW5lKGFlcyh5PW1lYW5FZjIpLCBjb2xvcj1zZXQxWzFdKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyBvZiB5ZWFyIikKcGYzIDwtIGdncGxvdChkYXRhPWRhdGEsIGFlcyh4PWRheV9vZl93ZWVrLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gMTo3LCBsYWJlbHM9YygnTW9uJywnVHVlJywnV2VkJywnVGh1JywnRnJpJywnU2F0JywnU3VuJykpICsKICBnZW9tX2xpbmUoZGF0YT1kYXRhLmZyYW1lKHg9MTo3LHk9RWZfZGF5X29mX3dlZWspLCBhZXMoeD14LCB5PUVmX2RheV9vZl93ZWVrKSwgY29sb3I9c2V0MVsxXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgb2Ygd2VlayIpCk49bGVuZ3RoKGRhdGEkaWQpCnBmM2IgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYzID0gRWYzKkVmMS8xMDApICU+JQogIGdncGxvdChhZXMoeD1kYXRlLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBnZW9tX3BvaW50KGFlcyh5PUVmMyksIGNvbG9yPXNldDFbMV0sIHNpemU9MC4xKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg5LTA4LTAxIikseT0oRWYzKkVmMS8xMDApW2MoKE4tNSk6KE4tNCksIE4sIE4tNildLGxhYmVsPWMoIk1vbiIsIlR1ZSIsIlNhdCIsIlN1biIpKQpmMTMgPC0gZGF0YSAlPiUgZmlsdGVyKHllYXI9PTE5ODgpJT4lc2VsZWN0KGRheSxkYXRlKSU+JW11dGF0ZSh5PUVmNGZsb2F0KSU+JWZpbHRlcihkYXk9PTEzKQpwZjJiIDwtZGF0YS5mcmFtZSh4PWFzLkRhdGUoIjE5ODgtMDEtMDEiKSswOjM2NSwgeT1FZjRmbG9hdCkgJT4lCiAgZ2dwbG90KGFlcyh4PXgseT15KSkgKyBnZW9tX2xpbmUoY29sb3I9c2V0MVsxXSkgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyBvZiB5ZWFyIikgKwogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMDEtMDEiKSx5PUVmNGZsb2F0WzFdLTEsbGFiZWw9Ik5ldyB5ZWFyIikgKwogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMDItMTQiKSx5PUVmNGZsb2F0WzQ1XSsxLjUsbGFiZWw9IlZhbGVudGluZSdzIGRheSIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTAyLTI5IikseT1FZjRmbG9hdFs2MF0tMi41LGxhYmVsPSJMZWFwIGRheSIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTA0LTAxIikseT1FZjRmbG9hdFs5Ml0tMS41LGxhYmVsPSJBcHJpbCAxc3QiKSArIAogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMDctMDQiKSx5PUVmNGZsb2F0WzE4Nl0tMS41LGxhYmVsPSJJbmRlcGVuZGVuY2UgZGF5IikgKwogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMTAtMzEiKSx5PUVmNGZsb2F0WzMwNV0tMS41LGxhYmVsPSJIYWxsb3dlZW4iKSArIAogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMTItMjQiKSx5PUVmNGZsb2F0WzM2MF0tMixsYWJlbD0iQ2hyaXN0bWFzIikgKwogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMDUtMzAiKSx5PUVmNGZsb2F0WzE1MV0tMixsYWJlbD0iTWVtb3JpYWwgZGF5IikgKwogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMDktMDUiKSx5PUVmNGZsb2F0WzI0OV0tMS41LGxhYmVsPSJMYWJvciBkYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMTEtMjQiKSx5PUVmNGZsb2F0WzMyOV0tMSxsYWJlbD0iVGhhbmtzZ2l2aW5nIikrCiAgZ2VvbV9wb2ludChkYXRhPWYxMyxhZXMoeD1kYXRlLHk9eSksIHNpemU9Mywgc2hhcGU9MSkKKHBmICsgcGYxKSAvIChwZjIgKyBwZjNiKSAvIChwZjJiKQoKIycgU2FtcGxlIHNob3J0IGNoYWlucyB1c2luZyB0aGUgZWFybHkgc3RvcHBlZCBvcHRpbWl6YXRpb24gcmVzdWx0IGFzCiMnIGluaXRpYWwgdmFsdWVzIChhbHRob3VnaCB0aGUgcmVzdWx0IGZyb20gc2hvcnQgY2hhaW5zIGNhbiBiZSB1c2VmdWwKIycgaW4gYSBxdWljayB3b3JrZmxvdywgdGhlIHJlc3VsdCBzaG91bGQgbm90IGJlIHVzZWQgYXMgdGhlIGZpbmFsCiMnIHJlc3VsdCkuCmluaXQ4IDwtIHNhcHBseShjKCdpbnRlcmNlcHQwJywnbGVuZ3Roc2NhbGVfZjEnLCdsZW5ndGhzY2FsZV9mMicsJ2xlbmd0aHNjYWxlX2czJywKICAgICAgICAgICAgICAgICAgJ3NpZ21hX2YxJywnc2lnbWFfZjInLCdzaWdtYV9nMycsJ3NpZ21hX2Y0Jywnc2lnbWEnLAogICAgICAgICAgICAgICAgICAnYmV0YV9mMScsJ2JldGFfZjInLCdiZXRhX2YzJywnYmV0YV9nMycsJ2JldGFfZjQnLCdiZXRhX2Y1JyksCiAgICAgICAgICAgICAgICBmdW5jdGlvbih2YXJpYWJsZSkge2FzLm51bWVyaWMoc3Vic2V0KG9kcmF3czgsIHZhcmlhYmxlPXZhcmlhYmxlKSl9KQojKyBmaXQ4LCByZXN1bHRzPSdoaWRlJwpmaXQ4IDwtIG1vZGVsOCRzYW1wbGUoZGF0YT1zdGFuZGF0YTgsIGl0ZXJfd2FybXVwPTEwMCwgaXRlcl9zYW1wbGluZz0xMDAsIGNoYWlucz00LCBwYXJhbGxlbF9jaGFpbnM9NCwKICAgICAgICAgICAgICAgICAgICAgIGluaXQ9ZnVuY3Rpb24oKSB7IGluaXQ4IH0sIHJlZnJlc2g9MTApCgojJyBDaGVjayB3aGV0aGVyIHBhcmFtZXRlcnMgaGF2ZSByZWFzb25hYmxlIHZhbHVlcwpkcmF3czggPC0gZml0OCRkcmF3cygpCnN1bW1hcmlzZV9kcmF3cyhzdWJzZXQoZHJhd3M4LCB2YXJpYWJsZT1jKCdpbnRlcmNlcHQnLCdzaWdtYV8nLCdsZW5ndGhzY2FsZV8nLCdzaWdtYScpLCByZWdleD1UUlVFKSkKc3VtbWFyaXNlX2RyYXdzKHN1YnNldChkcmF3czgsIHZhcmlhYmxlPWMoJ2JldGFfZjMnKSkpCgojJyBDb21wYXJlIHRoZSBtb2RlbCB0byB0aGUgZGF0YQpkcmF3czggPC0gYXNfZHJhd3NfbWF0cml4KGRyYXdzOCkKRWYgPC0gZXhwKGFwcGx5KHN1YnNldChkcmF3czgsIHZhcmlhYmxlPSdmJyksIDIsIG1lZGlhbikpCkVmMSA8LSBhcHBseShzdWJzZXQoZHJhd3M4LCB2YXJpYWJsZT0nZjEnKSwgMiwgbWVkaWFuKQpFZjEgPC0gZXhwKEVmMSAtIG1lYW4oRWYxKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCkVmMiA8LSBhcHBseShzdWJzZXQoZHJhd3M4LCB2YXJpYWJsZT0nZjInKSwgMiwgbWVkaWFuKQpFZjIgPC0gZXhwKEVmMiAtIG1lYW4oRWYyKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCkVmX2RheV9vZl93ZWVrIDwtIGFwcGx5KHN1YnNldChkcmF3czgsIHZhcmlhYmxlPSdmX2RheV9vZl93ZWVrJyksIDIsIG1lZGlhbikKRWZfZGF5X29mX3dlZWsgPC0gZXhwKEVmX2RheV9vZl93ZWVrIC0gbWVhbihFZl9kYXlfb2Zfd2VlaykgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZjMgPC0gYXBwbHkoc3Vic2V0KGRyYXdzOCwgdmFyaWFibGU9J2YzJyksIDIsIG1lZGlhbikKRWYzIDwtIGV4cChFZjMgLSBtZWFuKEVmMykgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZjQgPC0gYXBwbHkoc3Vic2V0KGRyYXdzOCwgdmFyaWFibGU9J2JldGFfZjQnKSwgMiwgbWVkaWFuKSpzZChsb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApKQpFZjQgPC0gZXhwKEVmNCkqMTAwCkVmbG9hdHMgPC0gYXBwbHkoc3Vic2V0KGRyYXdzOCwgdmFyaWFibGU9J2JldGFfZjUnKSwgMiwgbWVkaWFuKSpzZChsb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApKQpFZmxvYXRzIDwtIGV4cChFZmxvYXRzKSoxMDAKZmxvYXRzMTk4ODwtYyhtZW1vcmlhbF9kYXlzWzIwXSwgbGFib3JfZGF5c1tjKDIwLDQwKV0sIHRoYW5rc2dpdmluZ19kYXlzW2MoMjAsNDApXSktNjkzOQpFZjRmbG9hdCA8LSBFZjQKRWY0ZmxvYXRbZmxvYXRzMTk4OF0gPC0gRWY0ZmxvYXRbZmxvYXRzMTk4OF0qRWZsb2F0c1tjKDEsMiwyLDMsMyldLzEwMApwZiA8LSBkYXRhICU+JQogIG11dGF0ZShFZiA9IEVmKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9wb2ludChhZXMoeT1FZiksIGNvbG9yPXNldDFbMV0sIGFscGhhPTAuMikgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMiKQpwZjEgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYxID0gRWYxKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9saW5lKGFlcyh5PUVmMSksIGNvbG9yPXNldDFbMV0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIikKcGYyIDwtIGRhdGEgJT4lCiAgbXV0YXRlKEVmMiA9IEVmMikgJT4lCiAgZ3JvdXBfYnkoZGF5X29mX3llYXIyKSAlPiUKICBzdW1tYXJpc2UobWVhbmJpcnRocz1tZWFuKGJpcnRoc19yZWxhdGl2ZTEwMCksIG1lYW5FZjI9bWVhbihFZjIpKSAlPiUKICBnZ3Bsb3QoYWVzKHg9YXMuRGF0ZSgiMTk4Ny0xMi0zMSIpK2RheV9vZl95ZWFyMiwgeT1tZWFuYmlydGhzKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKSArCiAgZ2VvbV9saW5lKGFlcyh5PW1lYW5FZjIpLCBjb2xvcj1zZXQxWzFdKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyBvZiB5ZWFyIikKcGYzIDwtIGdncGxvdChkYXRhPWRhdGEsIGFlcyh4PWRheV9vZl93ZWVrLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gMTo3LCBsYWJlbHM9YygnTW9uJywnVHVlJywnV2VkJywnVGh1JywnRnJpJywnU2F0JywnU3VuJykpICsKICBnZW9tX2xpbmUoZGF0YT1kYXRhLmZyYW1lKHg9MTo3LHk9RWZfZGF5X29mX3dlZWspLCBhZXMoeD14LCB5PUVmX2RheV9vZl93ZWVrKSwgY29sb3I9c2V0MVsxXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgb2Ygd2VlayIpCk49bGVuZ3RoKGRhdGEkaWQpCnBmM2IgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYzID0gRWYzKkVmMS8xMDApICU+JQogIGdncGxvdChhZXMoeD1kYXRlLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBnZW9tX3BvaW50KGFlcyh5PUVmMyksIGNvbG9yPXNldDFbMV0sIHNpemU9MC4xKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg5LTA4LTAxIikseT0oRWYzKkVmMS8xMDApW2MoKE4tNSk6KE4tNCksIE4sIE4tNildLGxhYmVsPWMoIk1vbiIsIlR1ZSIsIlNhdCIsIlN1biIpKQpmMTMgPC0gZGF0YSAlPiUgZmlsdGVyKHllYXI9PTE5ODgpJT4lc2VsZWN0KGRheSxkYXRlKSU+JW11dGF0ZSh5PUVmNGZsb2F0KSU+JWZpbHRlcihkYXk9PTEzKQpwZjJiIDwtZGF0YS5mcmFtZSh4PWFzLkRhdGUoIjE5ODgtMDEtMDEiKSswOjM2NSwgeT1FZjRmbG9hdCkgJT4lCiAgZ2dwbG90KGFlcyh4PXgseT15KSkgKyBnZW9tX2xpbmUoY29sb3I9c2V0MVsxXSkgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyBvZiB5ZWFyIikgKwogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMDEtMDEiKSx5PUVmNGZsb2F0WzFdLTEsbGFiZWw9Ik5ldyB5ZWFyIikgKwogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMDItMTQiKSx5PUVmNGZsb2F0WzQ1XSsxLjUsbGFiZWw9IlZhbGVudGluZSdzIGRheSIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTAyLTI5IikseT1FZjRmbG9hdFs2MF0tMi41LGxhYmVsPSJMZWFwIGRheSIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTA0LTAxIikseT1FZjRmbG9hdFs5Ml0tMS41LGxhYmVsPSJBcHJpbCAxc3QiKSArIAogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMDctMDQiKSx5PUVmNGZsb2F0WzE4Nl0tMS41LGxhYmVsPSJJbmRlcGVuZGVuY2UgZGF5IikgKwogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMTAtMzEiKSx5PUVmNGZsb2F0WzMwNV0tMS41LGxhYmVsPSJIYWxsb3dlZW4iKSArIAogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMTItMjQiKSx5PUVmNGZsb2F0WzM2MF0tMixsYWJlbD0iQ2hyaXN0bWFzIikgKwogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMDUtMzAiKSx5PUVmNGZsb2F0WzE1MV0tMixsYWJlbD0iTWVtb3JpYWwgZGF5IikgKwogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMDktMDUiKSx5PUVmNGZsb2F0WzI0OV0tMS41LGxhYmVsPSJMYWJvciBkYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMTEtMjQiKSx5PUVmNGZsb2F0WzMyOV0tMSxsYWJlbD0iVGhhbmtzZ2l2aW5nIikrCiAgZ2VvbV9wb2ludChkYXRhPWYxMyxhZXMoeD1kYXRlLHk9eSksIHNpemU9Mywgc2hhcGU9MSkKKHBmICsgcGYxKSAvIChwZjIgKyBwZjNiKSAvIChwZjJiKQoKIycgVGhlIGluZmVyZW5jZSBmb3IgdGhlIG1vZGVsIHdvcmtzIGZpbmUsIHdoaWNoIGhpbnRzIHRoYXQgb3VyIFJIUwojJyBpbXBsZW1lbnRhdGlvbiBmb3IgdGhlIG1vZGVsIDUgd2FzIHdyb25nIG9yIGhhZCB2ZXJ5IGRpZmZpY3VsdAojJyBwb3N0ZXJpb3IuIEJlZm9yZSB0ZXN0aW5nIFJIUyBhZ2Fpbiwgd2UnbGwgdGVzdCB3aXRoIGFuIGVhc2llciB0bwojJyBpbXBsZW1lbnQgU3R1ZGVudCdzICR0JCBwcmlvciB3aGV0aGVyIGxvbmcgdGFpbGVkIHByaW9yIGZvciBkYXkgb2YKIycgeWVhciBlZmZlY3QgaXMgcmVhc29uYWJsZS4gVGhlc2UgZXhwZXJpbWVudHMgaGVscCBhbHNvIHRvIGZpbmQgb3V0CiMnIHdoZXRoZXIgdGhlIGRheSBvZiB5ZWFyIGVmZmVjdCBpcyBzZW5zaXRpdmUgdG8gdGhlIHByaW9yIGNob2ljZS4KIycKIycKIycgIyMjIE1vZGVsIDgrdF9udTogZGF5IG9mIHllYXIgZWZmZWN0IHdpdGggU3R1ZGVudCdzIHQgcHJpb3IKIycgCiMnIENvbXBpbGUgU3RhbiBtb2RlbCA4ICsgdF9udSBbZ3BiZjh0bnUuc3Rhbl0oaHR0cHM6Ly9naXRodWIuY29tL2F2ZWh0YXJpL2Nhc2VzdHVkaWVzL2Jsb2IvbWFzdGVyL0JpcnRoZGF5cy9ncGJmOHRudS5zdGFuKQojKyBtb2RlbDh0bnUsIHJlc3VsdHM9J2hpZGUnCm1vZGVsOHRudSA8LSBjbWRzdGFuX21vZGVsKHN0YW5fZmlsZSA9IHJvb3QoIkJpcnRoZGF5cyIsICJncGJmOHRudS5zdGFuIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGluY2x1ZGVfcGF0aHMgPSByb290KCJCaXJ0aGRheXMiKSkKCiMnIE9wdGltaXppbmcgaXMgZmFzdGVyIHRoYW4gc2FtcGxpbmcgKGFsdGhvdWdoIHRoaXMgcmVzdWx0IGNhbiBiZQojJyB1c2VmdWwgaW4gYSBxdWljayB3b3JrZmxvdywgdGhlIHJlc3VsdCBzaG91bGQgbm90IGJlIHVzZWQgYXMgdGhlCiMnIGZpbmFsIHJlc3VsdCkuCiMrIG9wdDh0bnUsIHJlc3VsdHM9J2hpZGUnCm9wdDh0bnUgPC0gbW9kZWw4dG51JG9wdGltaXplKGRhdGE9c3RhbmRhdGE4LCBpbml0PTAuMSwgYWxnb3JpdGhtPSdsYmZncycsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhpc3Rvcnk9MTAwLCB0b2xfb2JqPTEwKQpvZHJhd3M4dG51IDwtIG9wdDh0bnUkZHJhd3MoKQoKIycgU2FtcGxlIHNob3J0IGNoYWlucyB1c2luZyB0aGUgZWFybHkgc3RvcHBlZCBvcHRpbWl6YXRpb24gcmVzdWx0IGFzCiMnIGluaXRpYWwgdmFsdWVzIChhbHRob3VnaCB0aGUgcmVzdWx0IGZyb20gc2hvcnQgY2hhaW5zIGNhbiBiZSB1c2VmdWwKIycgaW4gYSBxdWljayB3b3JrZmxvdywgdGhlIHJlc3VsdCBzaG91bGQgbm90IGJlIHVzZWQgYXMgdGhlIGZpbmFsCiMnIHJlc3VsdCkuCmluaXQ4dG51IDwtIHNhcHBseShjKCdpbnRlcmNlcHQwJywnbGVuZ3Roc2NhbGVfZjEnLCdsZW5ndGhzY2FsZV9mMicsJ2xlbmd0aHNjYWxlX2czJywKICAgICAgICAgICAgICAgICAgJ3NpZ21hX2YxJywnc2lnbWFfZjInLCdzaWdtYV9nMycsJ3NpZ21hX2Y0JywnbnVfZjQnLCdzaWdtYScsCiAgICAgICAgICAgICAgICAgICdiZXRhX2YxJywnYmV0YV9mMicsJ2JldGFfZjMnLCdiZXRhX2czJywnYmV0YV9mNCcsJ2JldGFfZjUnKSwKICAgICAgICAgICAgICAgIGZ1bmN0aW9uKHZhcmlhYmxlKSB7YXMubnVtZXJpYyhzdWJzZXQob2RyYXdzOHRudSwgdmFyaWFibGU9dmFyaWFibGUpKX0pCiMrIGZpdDh0bnUsIHJlc3VsdHM9J2hpZGUnCmZpdDh0bnUgPC0gbW9kZWw4dG51JHNhbXBsZShkYXRhPXN0YW5kYXRhOCwgaXRlcl93YXJtdXA9MTAwLCBpdGVyX3NhbXBsaW5nPTEwMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoYWlucz00LCBwYXJhbGxlbF9jaGFpbnM9NCwKICAgICAgICAgICAgICAgICAgICAgIGluaXQ9ZnVuY3Rpb24oKSB7IGluaXQ4dG51IH0sIHJlZnJlc2g9MTApCgojJyBDaGVjayB3aGV0aGVyIHBhcmFtZXRlcnMgaGF2ZSByZWFzb25hYmxlIHZhbHVlcwpkcmF3czh0bnUgPC0gZml0OHRudSRkcmF3cygpCnN1bW1hcmlzZV9kcmF3cyhzdWJzZXQoZHJhd3M4dG51LCB2YXJpYWJsZT1jKCdpbnRlcmNlcHQnLCdzaWdtYV8nLCdsZW5ndGhzY2FsZV8nLCdzaWdtYScsJ251XycpLCByZWdleD1UUlVFKSkKIycgUG9zdGVyaW9yIG9mIGRlZ3JlZXMgb2YgZnJlZWRvbSBgbnVfZjRgIGlzIHZlcnkgY2xvc2UgdG8gMSwgYW5kCiMnIHRodXMgdGhlIGRpc3RyaWJ1dGlvbiBpcyB2ZXJ5IGNsb3NlIHRvIENhdWNoeS4gVGhpcyBpcyBzdHJvbmcKIycgZXZpZGVuY2UgdGhhdCB0aGUgZGlzdHJpYnV0aW9uIG9mIGRheSBvZiB5ZWFyIGVmZmVjdHMgaXMgZmFyIGZyb20KIycgbm9ybWFsLCBldmVuIGlmIENhdWNoeSB3b3VsZCBub3QgYmUgdGhlIGNvcnJlY3QgZGlzdHJpYnV0aW9uLgoKIycgQ29tcGFyZSB0aGUgbW9kZWwgdG8gdGhlIGRhdGEKZHJhd3M4IDwtIGFzX2RyYXdzX21hdHJpeChkcmF3czh0bnUpCkVmIDwtIGV4cChhcHBseShzdWJzZXQoZHJhd3M4LCB2YXJpYWJsZT0nZicpLCAyLCBtZWRpYW4pKQpFZjEgPC0gYXBwbHkoc3Vic2V0KGRyYXdzOCwgdmFyaWFibGU9J2YxJyksIDIsIG1lZGlhbikKRWYxIDwtIGV4cChFZjEgLSBtZWFuKEVmMSkgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZjIgPC0gYXBwbHkoc3Vic2V0KGRyYXdzOCwgdmFyaWFibGU9J2YyJyksIDIsIG1lZGlhbikKRWYyIDwtIGV4cChFZjIgLSBtZWFuKEVmMikgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZl9kYXlfb2Zfd2VlayA8LSBhcHBseShzdWJzZXQoZHJhd3M4LCB2YXJpYWJsZT0nZl9kYXlfb2Zfd2VlaycpLCAyLCBtZWRpYW4pCkVmX2RheV9vZl93ZWVrIDwtIGV4cChFZl9kYXlfb2Zfd2VlayAtIG1lYW4oRWZfZGF5X29mX3dlZWspICsgbWVhbihsb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApKSkKRWYzIDwtIGFwcGx5KHN1YnNldChkcmF3czgsIHZhcmlhYmxlPSdmMycpLCAyLCBtZWRpYW4pCkVmMyA8LSBleHAoRWYzIC0gbWVhbihFZjMpICsgbWVhbihsb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApKSkKRWY0IDwtIGFwcGx5KHN1YnNldChkcmF3czgsIHZhcmlhYmxlPSdiZXRhX2Y0JyksIDIsIG1lZGlhbikqc2QobG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkKRWY0IDwtIGV4cChFZjQpKjEwMApFZmxvYXRzIDwtIGFwcGx5KHN1YnNldChkcmF3czgsIHZhcmlhYmxlPSdiZXRhX2Y1JyksIDIsIG1lZGlhbikqc2QobG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkKRWZsb2F0cyA8LSBleHAoRWZsb2F0cykqMTAwCmZsb2F0czE5ODg8LWMobWVtb3JpYWxfZGF5c1syMF0sIGxhYm9yX2RheXNbYygyMCw0MCldLCB0aGFua3NnaXZpbmdfZGF5c1tjKDIwLDQwKV0pLTY5MzkKRWY0ZmxvYXQgPC0gRWY0CkVmNGZsb2F0W2Zsb2F0czE5ODhdIDwtIEVmNGZsb2F0W2Zsb2F0czE5ODhdKkVmbG9hdHNbYygxLDIsMiwzLDMpXS8xMDAKcGYgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYgPSBFZikgJT4lCiAgZ2dwbG90KGFlcyh4PWRhdGUsIHk9YmlydGhzX3JlbGF0aXZlMTAwKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIGdlb21fcG9pbnQoYWVzKHk9RWYpLCBjb2xvcj1zZXQxWzFdLCBhbHBoYT0wLjIpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIikKcGYxIDwtIGRhdGEgJT4lCiAgbXV0YXRlKEVmMSA9IEVmMSkgJT4lCiAgZ2dwbG90KGFlcyh4PWRhdGUsIHk9YmlydGhzX3JlbGF0aXZlMTAwKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIGdlb21fbGluZShhZXMoeT1FZjEpLCBjb2xvcj1zZXQxWzFdKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyIpCnBmMiA8LSBkYXRhICU+JQogIG11dGF0ZShFZjIgPSBFZjIpICU+JQogIGdyb3VwX2J5KGRheV9vZl95ZWFyMikgJT4lCiAgc3VtbWFyaXNlKG1lYW5iaXJ0aHM9bWVhbihiaXJ0aHNfcmVsYXRpdmUxMDApLCBtZWFuRWYyPW1lYW4oRWYyKSkgJT4lCiAgZ2dwbG90KGFlcyh4PWFzLkRhdGUoIjE5ODctMTItMzEiKStkYXlfb2ZfeWVhcjIsIHk9bWVhbmJpcnRocykpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikgKwogIGdlb21fbGluZShhZXMoeT1tZWFuRWYyKSwgY29sb3I9c2V0MVsxXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgb2YgeWVhciIpCnBmMyA8LSBnZ3Bsb3QoZGF0YT1kYXRhLCBhZXMoeD1kYXlfb2Zfd2VlaywgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IDE6NywgbGFiZWxzPWMoJ01vbicsJ1R1ZScsJ1dlZCcsJ1RodScsJ0ZyaScsJ1NhdCcsJ1N1bicpKSArCiAgZ2VvbV9saW5lKGRhdGE9ZGF0YS5mcmFtZSh4PTE6Nyx5PUVmX2RheV9vZl93ZWVrKSwgYWVzKHg9eCwgeT1FZl9kYXlfb2Zfd2VlayksIGNvbG9yPXNldDFbMV0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIG9mIHdlZWsiKQpOPWxlbmd0aChkYXRhJGlkKQpwZjNiIDwtIGRhdGEgJT4lCiAgbXV0YXRlKEVmMyA9IEVmMypFZjEvMTAwKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9wb2ludChhZXMoeT1FZjMpLCBjb2xvcj1zZXQxWzFdLCBzaXplPTAuMSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMiKSArCiAgYW5ub3RhdGUoInRleHQiLHg9YXMuRGF0ZSgiMTk4OS0wOC0wMSIpLHk9KEVmMypFZjEvMTAwKVtjKChOLTUpOihOLTQpLCBOLCBOLTYpXSxsYWJlbD1jKCJNb24iLCJUdWUiLCJTYXQiLCJTdW4iKSkKZjEzIDwtIGRhdGEgJT4lIGZpbHRlcih5ZWFyPT0xOTg4KSU+JXNlbGVjdChkYXksZGF0ZSklPiVtdXRhdGUoeT1FZjRmbG9hdCklPiVmaWx0ZXIoZGF5PT0xMykKCnBmMmIgPC1kYXRhLmZyYW1lKHg9YXMuRGF0ZSgiMTk4OC0wMS0wMSIpKzA6MzY1LCB5PUVmNGZsb2F0KSAlPiUKICBnZ3Bsb3QoYWVzKHg9eCx5PXkpKSArIGdlb21fbGluZShjb2xvcj1zZXQxWzFdKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCBkYXRlX2xhYmVscyA9ICIlYiIpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIG9mIHllYXIiKSArCiAgYW5ub3RhdGUoInRleHQiLHg9YXMuRGF0ZSgiMTk4OC0wMS0wMSIpLHk9RWY0ZmxvYXRbMV0tMSxsYWJlbD0iTmV3IHllYXIiKSArCiAgYW5ub3RhdGUoInRleHQiLHg9YXMuRGF0ZSgiMTk4OC0wMi0xNCIpLHk9RWY0ZmxvYXRbNDVdKzEuNSxsYWJlbD0iVmFsZW50aW5lJ3MgZGF5IikgKwogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMDItMjkiKSx5PUVmNGZsb2F0WzYwXS0yLjUsbGFiZWw9IkxlYXAgZGF5IikgKwogIGFubm90YXRlKCJ0ZXh0Iix4PWFzLkRhdGUoIjE5ODgtMDQtMDEiKSx5PUVmNGZsb2F0WzkyXS0xLjUsbGFiZWw9IkFwcmlsIDFzdCIpICsgCiAgYW5ub3RhdGUoInRleHQiLHg9YXMuRGF0ZSgiMTk4OC0wNy0wNCIpLHk9RWY0ZmxvYXRbMTg2XS0xLjUsbGFiZWw9IkluZGVwZW5kZW5jZSBkYXkiKSArCiAgYW5ub3RhdGUoInRleHQiLHg9YXMuRGF0ZSgiMTk4OC0xMC0zMSIpLHk9RWY0ZmxvYXRbMzA1XS0xLjUsbGFiZWw9IkhhbGxvd2VlbiIpICsgCiAgYW5ub3RhdGUoInRleHQiLHg9YXMuRGF0ZSgiMTk4OC0xMi0yNCIpLHk9RWY0ZmxvYXRbMzYwXS0yLGxhYmVsPSJDaHJpc3RtYXMiKSArCiAgYW5ub3RhdGUoInRleHQiLHg9YXMuRGF0ZSgiMTk4OC0wNS0zMCIpLHk9RWY0ZmxvYXRbMTUxXS0yLGxhYmVsPSJNZW1vcmlhbCBkYXkiKSArCiAgYW5ub3RhdGUoInRleHQiLHg9YXMuRGF0ZSgiMTk4OC0wOS0wNSIpLHk9RWY0ZmxvYXRbMjQ5XS0xLjUsbGFiZWw9IkxhYm9yIGRheSIpICsgCiAgYW5ub3RhdGUoInRleHQiLHg9YXMuRGF0ZSgiMTk4OC0xMS0yNCIpLHk9RWY0ZmxvYXRbMzI5XS0xLGxhYmVsPSJUaGFua3NnaXZpbmciKSsKICBnZW9tX3BvaW50KGRhdGE9ZjEzLGFlcyh4PWRhdGUseT15KSwgc2l6ZT0zLCBzaGFwZT0xKQoocGYgKyBwZjEpIC8gKHBmMiArIHBmM2IpIC8gKHBmMmIpCgojJyBUaGUgb3RoZXIgZWZmZWN0cyBzZWVtIHRvIGJlIHF1aXRlIHNpbWlsYXIgYXMgd2l0aCB0aGUgcHJldmlvdXMKIycgbW9kZWwsIGJ1dCB0aGUgZGF5IG9mIHllYXIgZWZmZWN0cyBhcmUgY2xlYXJseSBkaWZmZXJlbnQgd2l0aCBtb3N0CiMnIGRheXMgaGF2aW5nIG5vbi1kZXRlY3RhYmxlIGVmZmVjdC4gVGhlcmUgYXJlIGFsc28gZWZmZWN0cyB0aGF0CiMnIHNlZW1lZCB0byBiZSBxdWl0ZSBjbGVhciBpbiBub3JtYWwgcHJpb3IgbW9kZWwgc3VjaCBhcyAxM3RoIGRheSBvZgojJyBtb250aCBlZmZlY3QsIHdoaWNoIGlzIG5vdCB2aXNpYmxlIGFueW1vcmUuIEFzIHRoZSBwb3N0ZXJpb3Igb2YKIycgZGVncmVlcyBvZiBmcmVlZG9tIGB0X251YCB3YXMgY29uY2VudHJhdGVkIGNsb3NlIHRvIDEsIGl0J3MgbGlrZWx5CiMnIHRoYXQgdGhlIG5vcm1hbCBwcmlvciBmb3IgZGF5IG9mIHllYXIgZWZmZWN0IGNhbid0IGJlIHRoZSBiZXN0LiBTbwojJyBmYXIgd2UgaGFkbid0IHVzZWQgbW9kZWwgY29tcGFyaXNvbiBzdWNoIGFzIGxlYXZlLW9uZS1vdXQKIycgY3Jvc3MtdmFsaWRhdGlvbiAoTE9PLUNWKSBhcyBlYWNoIGFkZGVkIGNvbXBvbmVudCBoYWQgcXVhbGl0YXRpdmVseQojJyBiaWcgYW5kIHJlYXNvbmFibGUgZWZmZWN0LiBOb3cgYXMgZGF5IG9mIHllYXIgZWZmZWN0IGlzIHNlbnNpdGl2ZQojJyB0byBwcmlvciBjaG9pY2UsIGJ1dCBpdCdzIG5vdCBjbGVhciBob3cgbXVjaCBiZXR0ZXIgQ2F1Y2h5IHByaW9yCiMnIGRpc3RyaWJ1dGlvbiBpcyB3ZSB1c2UgTE9PLUNWIHRvIGNvbXBhcmUgdGhlIG1vZGVscy4KbG9vOCA8LSBmaXQ4JGxvbygpCmxvbzh0bnUgPC0gZml0OHRudSRsb28oKQpsb29fY29tcGFyZShsaXN0KGBNb2RlbCA4IG5vcm1hbGA9bG9vOCxgTW9kZWwgOCBTdHVkZW50XCdzIHRgPWxvbzh0bnUpKQojJyBBcyB3ZSBjb3VsZCBoYXZlIGV4cGVjdGVkIGJhc2VkIG9uIHRoZSBwb3N0ZXJpb3Igb2YgYG51X2Y0YAojJyBTdHVkZW50J3MgdCBwcmlvciBvbiBkYXkgb2YgeWVhciBlZmZlY3RzIGlzIGJldHRlci4gQXMgbG93IGRlZ3JlZXMKIycgb2YgZnJlZWRvbSBpbmRpY2F0ZSBhIHRoaWNrIHRhaWxlZCBkaXN0cmlidXRpb24gZm9yIGRheSBvZiB5ZWFyCiMnIGVmZmVjdCBpcyBuZWVkZWQsIHdlIGRlY2lkZWQgdG8gdGVzdCBhZ2FpbiBSSFMgcHJpb3IuCiMnIAoKIycgIyMjIE1vZGVsIDgrUkhTOiBkYXkgb2YgeWVhciBlZmZlY3Qgd2l0aCBSSFMgcHJpb3IKIycKIycgTW9kZWwgNSBoYWQgUkhTIHByaW9yIGJ1dCB0aGUgcHJvYmxlbSB3YXMgdGhhdCBvcHRpbWl6YXRpb24gcmVzdWx0CiMnIHdhc24ndCBldmVuIGNsb3NlIHRvIHNlbnNpYmxlIGFuZCBNQ01DIHdhcyB2ZXJ5IHNsb3cuIEdpdmVuIHRoZQojJyBvdGhlciBtb2RlbHMgd2Ugbm93IGtub3cgdGhhdCB0aGUgcHJvYmxlbSBpcyBub3QgaW4gYWRkaW5nIGRheSBvZgojJyB5ZWFyIGVmZmVjdCBvciBjb21iaW5pbmcgaXQgd2l0aCB0aW1lIGRlcGVuZGVudCBtYWduaXR1ZGUgZm9yIHRoZQojJyBkYXkgb2Ygd2VlayBlZmZlY3QuIEl0IHdhcyBlYXNpZXIgbm93IHRvIGZvY3VzIG9uIGZpZ3VyaW5nIG91dCB0aGUKIycgcHJvYmxlbSBpbiBSSFMuIFNpbmNlIFJIUyBpcyBwcmVzZW50ZWQgYXMgYSBzY2FsZSBtaXh0dXJlIG9mCiMnIG5vcm1hbHMgaW52b2x2aW5nIGhpZXJhcmNoaWNhbCBwcmlvciwgaXQgaXMgY29tbW9uIHRvIHVzZQojJyBub24tY2VudGVyZWQgcGFyYW1ldGVyaXphdGlvbiBmb3IgUkhTIHByaW9yLiBOb24tY2VudGVyZWQKIycgcGFyYW1ldGVyaXphdGlvbiBpcyB1c2VmdWwgd2hlbiB0aGUgaW5mb3JtYXRpb24gZnJvbSB0aGUgbGlrZWxpaG9vZAojJyBpcyB3ZWFrIGFuZCB0aGUgcHJpb3IgZGVwZW5kZW5jeSBkb21pbmF0ZXMgaW4gdGhlIHBvc3RlcmlvcgojJyBkZXBlbmRlbmN5LiBSSFMgaXMgb2Z0ZW4gdXNlZCB3aGVuIHRoZXJlIGFyZSBsZXNzIG9ic2VydmF0aW9ucyB0aGFuCiMnIHVua25vd25zLiBJbiB0aGlzIHByb2JsZW0gZWFjaCB1bmtub3duIChvbmUgZGF5IG9mIHllYXIgZWZmZWN0KSBpcwojJyBpbmZvcm1lZCBieSBzZXZlcmFsIG9ic2VydmF0aW9ucyBmcm9tIGRpZmZlcmVudCB5ZWFycywgYW5kIHRoZW4gaXQKIycgbWlnaHQgYmUgdGhhdCB0aGUgY2VudGVyZWQgcGFyYW1ldGVyaXphdGlvbiBpcyBiZXR0ZXIuIEFuZCB0aGlzCiMnIHR1cm5lZCBvdXQgdG8gYmUgdHJ1ZSBhbmQgdGhlIGluZmVyZW5jZSBmb3IgbW9kZWwgOCB3aXRoIGNlbnRlcmVkCiMnIHBhcmFtZXRlcml6YXRpb24gUkhTIHByaW9yIG9uIGRheSBvZiB5ZWFyIGVmZmVjdCB3b3JrZWQgbXVjaCBiZXR0ZXIKIycgdGhhbiBmb3IgbW9kZWwgNS4gIChJbiBTdGFuIGl0IHdhcyBlYXN5IHRvIHRlc3Qgc3dpdGNoIGZyb20KIycgbm9uLWNlbnRlcmVkIHRvIGNlbnRlcmVkIHBhcmFtZXRlcml6YXRpb24gYnkgcmVtb3ZpbmcgdGhlIG11bHRwbGllcgojJyBmcm9tIG9uZSBvZiB0aGUgcGFyYW1ldGVyIGRlY2xhcmF0aW9ucykuCiMnCiMnIENvbXBpbGUgU3RhbiBtb2RlbCA4ICsgUkhTIFtncGJmOHJocy5zdGFuXShodHRwczovL2dpdGh1Yi5jb20vYXZlaHRhcmkvY2FzZXN0dWRpZXMvYmxvYi9tYXN0ZXIvQmlydGhkYXlzL2dwYmY4cmhzLnN0YW4pCiMrIG1vZGVsOHJocywgcmVzdWx0cz0naGlkZScKbW9kZWw4cmhzIDwtIGNtZHN0YW5fbW9kZWwoc3Rhbl9maWxlID0gcm9vdCgiQmlydGhkYXlzIiwgImdwYmY4cmhzLnN0YW4iKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5jbHVkZV9wYXRocyA9IHJvb3QoIkJpcnRoZGF5cyIpKQoKIycgQWRkIGEgZ2xvYmFsIHNjYWxlIGZvciBSSFMgcHJpb3IKc3RhbmRhdGE4IDwtIGMoc3RhbmRhdGE4LAogICAgICAgICAgICAgICBzY2FsZV9nbG9iYWw9MC4xKSAjIGdsb2JhbCBzY2FsZSBmb3IgUkhTIHByaW9yCgojJyBPcHRpbWl6aW5nIGlzIGZhc3RlciB0aGFuIHNhbXBsaW5nIChhbHRob3VnaCB0aGlzIHJlc3VsdCBjYW4gYmUKIycgdXNlZnVsIGluIGEgcXVpY2sgd29ya2Zsb3csIHRoZSByZXN1bHQgc2hvdWxkIG5vdCBiZSB1c2VkIGFzIHRoZQojJyBmaW5hbCByZXN1bHQpLgojKyBvcHQ4cmhzLCByZXN1bHRzPSdoaWRlJwpvcHQ4cmhzIDwtIG1vZGVsOHJocyRvcHRpbWl6ZShkYXRhPXN0YW5kYXRhOCwgaW5pdD0wLjEsIGFsZ29yaXRobT0nbGJmZ3MnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoaXN0b3J5PTEwMCwgdG9sX29iaj0xMCkKb2RyYXdzOHJocyA8LSBvcHQ4cmhzJGRyYXdzKCkKCiMnIFNhbXBsZSBzaG9ydCBjaGFpbnMgdXNpbmcgdGhlIG9wdGltaXphdGlvbiByZXN1bHQgYXMgaW5pdGlhbCB2YWx1ZXMKIycgKGFsdGhvdWdoIHRoZSByZXN1bHQgZnJvbSBzaG9ydCBjaGFpbnMgY2FuIGJlIHVzZWZ1bCBpbiBhIHF1aWNrCiMnIHdvcmtmbG93LCB0aGUgcmVzdWx0IHNob3VsZCBub3QgYmUgdXNlZCBhcyB0aGUgZmluYWwgcmVzdWx0KS4KaW5pdDhyaHMgPC0gc2FwcGx5KGMoJ2ludGVyY2VwdDAnLCdsZW5ndGhzY2FsZV9mMScsJ2xlbmd0aHNjYWxlX2YyJywnbGVuZ3Roc2NhbGVfZzMnLAogICAgICAgICAgICAgICAgICAnc2lnbWFfZjEnLCdzaWdtYV9mMicsJ3NpZ21hX2czJywnc2lnbWFfZjQnLCdzaWdtYScsCiAgICAgICAgICAgICAgICAgICdiZXRhX2YxJywnYmV0YV9mMicsJ2JldGFfZjMnLCdiZXRhX2czJywnYmV0YV9mNCcsJ2JldGFfZjUnLAogICAgICAgICAgICAgICAgICAndGF1X2Y0JywnbGFtYmRhX2Y0JywnY2F1eF9mNCcpLAogICAgICAgICAgICAgICAgZnVuY3Rpb24odmFyaWFibGUpIHthcy5udW1lcmljKHN1YnNldChvZHJhd3M4cmhzLCB2YXJpYWJsZT12YXJpYWJsZSkpfSkKIysgZml0OHJocywgcmVzdWx0cz0naGlkZScKZml0OHJocyA8LSBtb2RlbDhyaHMkc2FtcGxlKGRhdGE9c3RhbmRhdGE4LCBpdGVyX3dhcm11cD0xMDAsIGl0ZXJfc2FtcGxpbmc9MTAwLCBjaGFpbnM9NCwgcGFyYWxsZWxfY2hhaW5zPTQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbml0PWZ1bmN0aW9uKCkgeyBpbml0OHJocyB9LCByZWZyZXNoPTEwKQoKIycgQ2hlY2sgd2hldGhlciBwYXJhbWV0ZXJzIGhhdmUgcmVhc29uYWJsZSB2YWx1ZXMKZHJhd3M4cmhzIDwtIGZpdDhyaHMkZHJhd3MoKQpzdW1tYXJpc2VfZHJhd3Moc3Vic2V0KGRyYXdzOHJocywgdmFyaWFibGU9YygnaW50ZXJjZXB0Jywnc2lnbWFfJywnbGVuZ3Roc2NhbGVfJywnc2lnbWEnLCdudV8nKSwgcmVnZXg9VFJVRSkpCgojJyBDb21wYXJlIHRoZSBtb2RlbCB0byB0aGUgZGF0YQpkcmF3czggPC0gYXNfZHJhd3NfbWF0cml4KGRyYXdzOHJocykKRWYgPC0gZXhwKGFwcGx5KHN1YnNldChkcmF3czgsIHZhcmlhYmxlPSdmJyksIDIsIG1lZGlhbikpCkVmMSA8LSBhcHBseShzdWJzZXQoZHJhd3M4LCB2YXJpYWJsZT0nZjEnKSwgMiwgbWVkaWFuKQpFZjEgPC0gZXhwKEVmMSAtIG1lYW4oRWYxKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCkVmMiA8LSBhcHBseShzdWJzZXQoZHJhd3M4LCB2YXJpYWJsZT0nZjInKSwgMiwgbWVkaWFuKQpFZjIgPC0gZXhwKEVmMiAtIG1lYW4oRWYyKSArIG1lYW4obG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkpCkVmX2RheV9vZl93ZWVrIDwtIGFwcGx5KHN1YnNldChkcmF3czgsIHZhcmlhYmxlPSdmX2RheV9vZl93ZWVrJyksIDIsIG1lZGlhbikKRWZfZGF5X29mX3dlZWsgPC0gZXhwKEVmX2RheV9vZl93ZWVrIC0gbWVhbihFZl9kYXlfb2Zfd2VlaykgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZjMgPC0gYXBwbHkoc3Vic2V0KGRyYXdzOCwgdmFyaWFibGU9J2YzJyksIDIsIG1lZGlhbikKRWYzIDwtIGV4cChFZjMgLSBtZWFuKEVmMykgKyBtZWFuKGxvZyhkYXRhJGJpcnRoc19yZWxhdGl2ZTEwMCkpKQpFZjQgPC0gYXBwbHkoc3Vic2V0KGRyYXdzOCwgdmFyaWFibGU9J2JldGFfZjQnKSwgMiwgbWVkaWFuKSpzZChsb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApKQpFZjQgPC0gZXhwKEVmNCkqMTAwCkVmbG9hdHMgPC0gYXBwbHkoc3Vic2V0KGRyYXdzOCwgdmFyaWFibGU9J2JldGFfZjUnKSwgMiwgbWVkaWFuKSpzZChsb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDApKQpFZmxvYXRzIDwtIGV4cChFZmxvYXRzKSoxMDAKZmxvYXRzMTk4ODwtYyhtZW1vcmlhbF9kYXlzWzIwXSwgbGFib3JfZGF5c1tjKDIwLDQwKV0sIHRoYW5rc2dpdmluZ19kYXlzW2MoMjAsNDApXSktNjkzOQpFZjRmbG9hdCA8LSBFZjQKRWY0ZmxvYXRbZmxvYXRzMTk4OF0gPC0gRWY0ZmxvYXRbZmxvYXRzMTk4OF0qRWZsb2F0c1tjKDEsMiwyLDMsMyldLzEwMApwZiA8LSBkYXRhICU+JQogIG11dGF0ZShFZiA9IEVmKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9wb2ludChhZXMoeT1FZiksIGNvbG9yPXNldDFbMV0sIGFscGhhPTAuMikgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMiKQpwZjEgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYxID0gRWYxKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1iaXJ0aHNfcmVsYXRpdmUxMDApKSArIGdlb21fcG9pbnQoY29sb3I9c2V0MVsyXSwgYWxwaGE9MC4yKSArCiAgZ2VvbV9saW5lKGFlcyh5PUVmMSksIGNvbG9yPXNldDFbMV0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MTAwLCBjb2xvcj0nZ3JheScpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJSZWxhdGl2ZSBudW1iZXIgb2YgYmlydGhzIikKcGYyIDwtIGRhdGEgJT4lCiAgbXV0YXRlKEVmMiA9IEVmMikgJT4lCiAgZ3JvdXBfYnkoZGF5X29mX3llYXIyKSAlPiUKICBzdW1tYXJpc2UobWVhbmJpcnRocz1tZWFuKGJpcnRoc19yZWxhdGl2ZTEwMCksIG1lYW5FZjI9bWVhbihFZjIpKSAlPiUKICBnZ3Bsb3QoYWVzKHg9YXMuRGF0ZSgiMTk4Ny0xMi0zMSIpK2RheV9vZl95ZWFyMiwgeT1tZWFuYmlydGhzKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0sIGFscGhhPTAuMikgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIiKSArCiAgZ2VvbV9saW5lKGFlcyh5PW1lYW5FZjIpLCBjb2xvcj1zZXQxWzFdKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyBvZiB5ZWFyIikKcGYzIDwtIGdncGxvdChkYXRhPWRhdGEsIGFlcyh4PWRheV9vZl93ZWVrLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gMTo3LCBsYWJlbHM9YygnTW9uJywnVHVlJywnV2VkJywnVGh1JywnRnJpJywnU2F0JywnU3VuJykpICsKICBnZW9tX2xpbmUoZGF0YT1kYXRhLmZyYW1lKHg9MTo3LHk9RWZfZGF5X29mX3dlZWspLCBhZXMoeD14LCB5PUVmX2RheV9vZl93ZWVrKSwgY29sb3I9c2V0MVsxXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgb2Ygd2VlayIpCk49bGVuZ3RoKGRhdGEkaWQpCnBmM2IgPC0gZGF0YSAlPiUKICBtdXRhdGUoRWYzID0gRWYzKkVmMS8xMDApICU+JQogIGdncGxvdChhZXMoeD1kYXRlLCB5PWJpcnRoc19yZWxhdGl2ZTEwMCkpICsgZ2VvbV9wb2ludChjb2xvcj1zZXQxWzJdLCBhbHBoYT0wLjIpICsKICBnZW9tX3BvaW50KGFlcyh5PUVmMyksIGNvbG9yPXNldDFbMV0sIHNpemU9MC4xKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTEwMCwgY29sb3I9J2dyYXknKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUmVsYXRpdmUgbnVtYmVyIG9mIGJpcnRocyIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg5LTA4LTAxIikseT0oRWYzKkVmMS8xMDApW2MoKE4tNSk6KE4tNCksIE4sIE4tNildLGxhYmVsPWMoIk1vbiIsIlR1ZSIsIlNhdCIsIlN1biIpKQpmMTMgPC0gZGF0YSAlPiUgZmlsdGVyKHllYXI9PTE5ODgpJT4lc2VsZWN0KGRheSxkYXRlKSU+JW11dGF0ZSh5PUVmNGZsb2F0KSU+JWZpbHRlcihkYXk9PTEzKQoKcGYyYiA8LWRhdGEuZnJhbWUoeD1hcy5EYXRlKCIxOTg4LTAxLTAxIikrMDozNjUsIHk9RWY0ZmxvYXQpICU+JQogIGdncGxvdChhZXMoeD14LHk9eSkpICsgZ2VvbV9saW5lKGNvbG9yPXNldDFbMV0pICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiViIikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0xMDAsIGNvbG9yPSdncmF5JykgKwogIGxhYnMoeD0iRGF0ZSIsIHk9IlJlbGF0aXZlIG51bWJlciBvZiBiaXJ0aHMgb2YgeWVhciIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTAxLTAxIikseT1FZjRmbG9hdFsxXS0xLGxhYmVsPSJOZXcgeWVhciIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTAyLTE0IikseT1FZjRmbG9hdFs0NV0rMS41LGxhYmVsPSJWYWxlbnRpbmUncyBkYXkiKSArCiAgYW5ub3RhdGUoInRleHQiLHg9YXMuRGF0ZSgiMTk4OC0wMi0yOSIpLHk9RWY0ZmxvYXRbNjBdLTIuNSxsYWJlbD0iTGVhcCBkYXkiKSArCiAgYW5ub3RhdGUoInRleHQiLHg9YXMuRGF0ZSgiMTk4OC0wNC0wMSIpLHk9RWY0ZmxvYXRbOTJdLTEuNSxsYWJlbD0iQXByaWwgMXN0IikgKyAKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTA3LTA0IikseT1FZjRmbG9hdFsxODZdLTEuNSxsYWJlbD0iSW5kZXBlbmRlbmNlIGRheSIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTEwLTMxIikseT1FZjRmbG9hdFszMDVdLTEuNSxsYWJlbD0iSGFsbG93ZWVuIikgKyAKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTEyLTI0IikseT1FZjRmbG9hdFszNjBdLTIsbGFiZWw9IkNocmlzdG1hcyIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTA1LTMwIikseT1FZjRmbG9hdFsxNTFdLTIsbGFiZWw9Ik1lbW9yaWFsIGRheSIpICsKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTA5LTA1IikseT1FZjRmbG9hdFsyNDldLTEuNSxsYWJlbD0iTGFib3IgZGF5IikgKyAKICBhbm5vdGF0ZSgidGV4dCIseD1hcy5EYXRlKCIxOTg4LTExLTI0IikseT1FZjRmbG9hdFszMjldLTEsbGFiZWw9IlRoYW5rc2dpdmluZyIpKwogIGdlb21fcG9pbnQoZGF0YT1mMTMsYWVzKHg9ZGF0ZSx5PXkpLCBzaXplPTMsIHNoYXBlPTEpCihwZiArIHBmMSkgLyAocGYyICsgcGYzYikgLyAocGYyYikKCiMnIFZpc3VhbGx5IHdlIGdldCBxdWl0ZSBzaW1pbGFyIHJlc3VsdCBhcyB3aXRoIENhdWNoeSBwcmlvci4gV2hlbiB3ZQojJyBjb21wYXJlIHRoZSBtb2RlbHMgd2l0aCBMT08tQ1YsIENhdWNoeSBpcyBmYXZvcmVkIGluc3RlYWQgb2YgUkhTLgpsb284cmhzPC1maXQ4cmhzJGxvbygpCmxvb19jb21wYXJlKGxpc3QoYE1vZGVsIDggU3R1ZGVudHMgdGA9bG9vOHRudSxgTW9kZWwgOCBSSFNgPWxvbzhyaHMpKQojJyBJZiB3ZSBsb29rIGF0IHRoZSBMT08tc3RhY2tpbmcgbW9kZWwgd2VpZ2h0cywgdGhlIHByZWRpY3RpdmUKIycgcGVyZm9ybWFuY2UgY2FuIGJlIGltcHJvdmVkIGJ5IGNvbWJpbmluZyBDYXVjaHkgYW5kIFJIUyBwcmlvcnMgb24KIycgZGF5IG9mIHllYXIgZWZmZWN0IHdoaWNoIGluZGljYXRlcyB0aGF0IG5laXRoZXIgb2YgdGhlbSBpcyB2ZXJ5CiMnIGNsb3NlIHRvIHRydWUgZGlzdHJpYnV0aW9uLgpsb29fbW9kZWxfd2VpZ2h0cyhsaXN0KGBNb2RlbCA4IFN0dWRlbnRzIHRgPWxvbzh0bnUsYE1vZGVsIDggUkhTYD1sb284cmhzKSkKCiMnICMjIyBGdXJ0aGVyIGltcHJvdmVtZW50cyBmb3IgdGhlIGRheSBvZiB5ZWFyIGVmZmVjdAojJyAKIycgSXQncyB1bmxpa2VseSB0aGF0IGRheSBvZiB5ZWFyIGVmZmVjdCB3b3VsZCBiZSB1bnN0cnVjdHVyZWQgd2l0aAojJyBzb21lIGRpc3RyaWJ1dGlvbiBsaWtlIENhdWNoeSwgYW5kIHRodXMgaW5zdGVhZCBvZiB0cnlpbmcgdG8gZmluZCBhCiMnIHByaW9yIGRpc3RyaWJ1dGlvbiB0aGF0IHdvdWxkIGltcHJvdmUgTE9PLUNWLCBpdCB3b3VsZCBtYWtlIG1vcmUKIycgc2Vuc2UgdG8gZnVydGhlciBhZGQgc3RydWN0dXJhbCBpbmZvcm1hdGlvbi4gRm9yIGV4YW1wbGUsIGl0IHdvdWxkCiMnIGJlIHBvc3NpYmxlIHRvIGFkZCBtb3JlIGtub3duIHNwZWNpYWwgZGF5cyBhbmQgdGFrZSBpbnRvIGFjY291bnQKIycgdGhhdCBhIHNwZWNpYWwgZGF5IGVmZmVjdCBhbmQgd2Vla2VuZCBlZmZlY3QgcHJvYmFibHkgYXJlIG5vdAojJyBhZGRpdGl2ZS4gRnVydGhlcm1vcmUgaWYgdGhlcmUgYXJlIGxlc3MgYmlydGhzIGR1cmluZyBzb21lIGRheSwgdGhlCiMnIGJpcnRocyBuZWVkIHRvIGhhcHBlbiBzb21lIG90aGVyIGRheSBhbmQgaXQgY2FuIGJlIGFzc3VtZWQgdGhhdAojJyB0aGVyZSB3b3VsZCBiZSBjb3JyZXNwb25kaW5nIGV4Y2VzcyBvZiBiaXJ0aHMgYmVmb3JlIG9mIGFmdGVyIGEKIycgYmFuayBob2xpZGF5LiBUaGlzIHJpbmdpbmcgYXJvdW5kIGRheXMgd2l0aCBsZXNzIGJpcnRocyBpcyBub3QKIycgc2ltcGxlIGFzIGl0IGlzIGFsc28gYWZmZWN0ZWQgd2hldGhlciB0aGUgcHJldmlvdXMgYW5kIGZvbGxvd2luZwojJyBkYXlzIGFyZSB3ZWVrZW5kIGRheXMuIFRoaXMgYWxsIGdldHMgbW9yZSBjb21wbGljYXRlZCB0aGFuIHdlIHdhbnQKIycgdG8gaW5jbHVkZSBpbiB0aGlzIGNhc2Ugc3R1ZHksIGJ1dCB0aGUgcmVhZGVyIGNhbiBzZWUgaG93IHRoZQojJyBzaW1pbGFyIGdyYWR1YWwgbW9kZWwgYnVpbGRpbmcgY291bGQgYmUgbWFkZSBieSBhZGRpbmcgYWRkaXRpb25hbAojJyBjb21wb25lbnRzLiBFdmVudHVhbGx5IGl0IGlzIGxpa2VseSB0aGF0IHRoZXJlIHN0YXJ0cyB0byBiZSB3b3JyeQojJyBvZiBvdmVyZml0dGluZywgYnV0IGludGVncmF0aW9uIG92ZXIgdGhlIHVua25vd24gYWxsZXZpYXRlcyB0aGF0CiMnIGFuZCBsb29raW5nIGF0IHRoZSBwcmVkaWN0aXZlIHBlcmZvcm1hbmNlIGVzdGltYXRlcyBzdWNoIExPTy1DViBjYW4KIycgaGVscCB0byBkZWNpZGUgd2hlbiB0aGUgYWRkaXRpb25hbCBtb2RlbCBjb21wb25lbnRzIGRvbid0IGltcHJvdmUKIycgdGhlIHByZWRpY3RpdmUgcGVyZm9ybWFuY2Ugb3IgY2FuJ3QgYmUgd2VsbCBpZGVudGlmaWVkLgojJwojJyAjIyMgUXVhbnRpdGF0aXZlIHByZWRpY3RpdmUgcGVyZm9ybWFuY2UgZm9yIHRoZSBzZXJpZXMgb2YgbW9kZWxzCiMnIAojJyBXZSBkaWRuJ3QgdXNlIExPTy1DViB1bnRpbCBpbiB0aGUgZW5kLCBhcyB0aGUgcXVhbGl0YXRpdmUKIycgZGlmZmVyZW5jZXMgYmV0d2VlbiBtb2RlbHMgd2VyZSB2ZXJ5IGNvbnZpbmNpbmcuIFdlIGNhbiB1c2UgTE9PLUNWCiMnIHRvIGNoZWNrIGhvdyBiaWcgdGhlIGRpZmZlcmVuY2UgaW4gdGhlIHByZWRpY3RpdmUgcGVyZm9ybWFuY2UgYXJlCiMnIGFuZCBpZiB0aGUgZGlmZmVyZW5jZXMgYXJlIGJpZywgd2Uga25vdyB0aGF0IG1vZGVsIGF2ZXJhZ2luZyB0aGF0CiMnIHdvdWxkIHRha2UgaW50byBhY2NvdW50IHRoZSB1bmNlcnRhaW50eSB3b3VsZCBnaXZlIHdlaWdodHMgY2xvc2UgdG8KIycgemVybyBmb3IgYWxsIGJ1dCB0aGUgbW9zdCBlbGFib3JhdGUgbW9kZWxzLgpsb28xPC1maXQxJGxvbygpCmxvbzI8LWZpdDIkbG9vKCkKbG9vMzwtZml0MyRsb28oKQpsb280PC1maXQ0JGxvbygpCmxvbzY8LWZpdDYkbG9vKCkKbG9vNzwtZml0NyRsb28oKQpsb29fY29tcGFyZShsaXN0KGBNb2RlbCAxYD1sb28xLGBNb2RlbCAyYD1sb28yLGBNb2RlbCAzYD1sb28zLGBNb2RlbCA0YD1sb280LGBNb2RlbCA2YD1sb282LGBNb2RlbCA3YD1sb283LGBNb2RlbCA4ICsgdF9udWA9bG9vOHRudSkpCgojJyAjIyMgUmVzaWR1YWwgYW5hbHlzaXMKIycgCiMnIFdlIGNhbiBnZXQgZnVydGhlciBpZGVhcyBmb3IgaG93IHRvIGltcHJvdmUgdGhlIG1vZGVsIGFsc28gYnkKIycgbG9va2luZyBhdCB0aGUgcmVzaWR1YWxzLgpkcmF3czggPC0gYXNfZHJhd3NfbWF0cml4KGRyYXdzOHRudSkKRWYgPC0gZXhwKGFwcGx5KHN1YnNldChkcmF3czgsIHZhcmlhYmxlPSdmJyksIDIsIG1lZGlhbikpCmRhdGEgJT4lCiAgbXV0YXRlKEVmID0gRWYpICU+JQogIGdncGxvdChhZXMoeD1kYXRlLCB5PWxvZyhiaXJ0aHNfcmVsYXRpdmUxMDAvRWYpKSkgKyBnZW9tX3BvaW50KGNvbG9yPXNldDFbMl0pICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MCwgY29sb3I9J2dyYXknKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gIjEgeWVhciIsIGRhdGVfbGFiZWxzID0gIiVZIikgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueD1lbGVtZW50X2xpbmUoY29sb3I9J2dyYXknLHNpemU9MSkpCiMnIFdlIGNhbiBzZWUgc29tZSBzdHJ1Y3R1cmUsIHNwZWNpZmljYWxseSBpbiB5ZWFycyAxOTY5LS0xOTc4IHRoZQojJyByZXNpZHVhbCBoYXMgbmVnYXRpdmUgcGVhayBpbiB0aGUgbWlkZGxlIG9mIHRoZSB5ZWFyLCB3aGlsZSBpbiB5ZWFycwojJyAxOTgxLS0xOTg4IHRoZSByZXNpZHVhbCBoYXMgcG9zaXRpdmUgcGVhayBpbiB0aGUgbWlkZGxlIG9mIHRoZQojJyB5ZWFyLiBUaGlzIGtpbmQgb2YgcGF0dGVybiBhcHBlYXJzIGFzIHdlIHVzZSB0aGUgc2FtZSBzZWFzb25hbAojJyBlZmZlY3QgZm9yIGFsbCB5ZWFycywgYnV0IHRoZSBtYWduaXR1ZGUgb2Ygc2Vhc29uYWwgZWZmZWN0IGlzCiMnIGNoYW5naW5nLiBJdCB3b3VsZCBiZSBwb3NzaWJsZSB0byBtb2RpZnkgdGhlIG1vZGVsIHRvIGluY2x1ZGUKIycgZ3JhZHVhbGx5IGNoYW5naW5nIHNlYXNvbmFsIGVmZmVjdCwgYnV0IGxlYXZlIGl0IG91dCBmcm9tIHRoaXMgY2FzZQojJyBzdHVkeS4gCiMnCiMnIFRoZSBiZXN0IG1vZGVsIHNvIGZhciBleHBsYWlucyBhbHJlYWR5IDk0JSBvZiB0aGUgdmFyaWFuY2UgKExPTy1SMikuCmRyYXdzOCA8LSBhc19kcmF3c19tYXRyaXgoZHJhd3M4dG51KQpmIDwtIGV4cChzdWJzZXQoZHJhd3M4LCB2YXJpYWJsZT0nZicpKQpsb284dG51IDwtIGZpdDh0bnUkbG9vKHNhdmVfcHNpcz1UUlVFKQpFZmxvbyA8LSBFX2xvbyhmLCBwc2lzX29iamVjdD1sb284dG51JHBzaXNfb2JqZWN0KSR2YWx1ZQpMT09SMiA8LSAxLXZhcihsb2coZGF0YSRiaXJ0aHNfcmVsYXRpdmUxMDAvRWZsb28pKS92YXIobG9nKGRhdGEkYmlydGhzX3JlbGF0aXZlMTAwKSkKcHJpbnQoTE9PUjIsIGRpZ2l0cz0yKQojJyBBcyBpdCBzZWVtcyB3ZSBjb3VsZCBzdGlsbCBpbXByb3ZlIGJ5IGFkZGluZyBtb3JlIHN0cnVjdHVyZSBhbmQKIycgdGltZSB2YXJ5aW5nIHNlYXNvbmFsIGVmZmVjdCwgaXQgc2VlbXMgdGhlIHZhcmlhYmlsaXR5IGluIHRoZQojJyBudW1iZXIgb2YgYmlydGhzIGZyb20gZGF5IHRvIGRheSBpcyBxdWl0ZSB3ZWxsIHByZWRpY3RhYmxlLiBPZgojJyBjb3Vyc2UgYmlnIHBhcnQgb2YgdGhlIHZhcmlhdGlvbiBpcyBkdWUgdG8gcGxhbm5lZCBpbmR1Y2VkIGJpcnRocwojJyBhbmQgYy1zZWN0aW9ucywgYW5kIHRodXMgaG9zcGl0YWxzIGRvIGFscmVhZHkgY29udHJvbCB0aGUgbnVtYmVyIG9mCiMnIGJpcnRocyBwZXIgZGF5IGFuZCB0aGVyZSBpcyBubyByZWFsbHkgcHJhY3RpY2FsIHVzZSBmb3IgdGhlCiMnIHJlc3VsdC4gSG93ZXZlciB0aGVyZSBhcmUgcGxlbnR5IG9mIHNpbWlsYXIgdGltZSBzZXJpZXMsIGZvcgojJyBleGFtcGxlLCBpbiBjb25zdW1lciBiZWhhdmlvciB0aGF0IGFyZSBhZmZlY3RlZCBieSBzcGVjaWFsIGRheXMuCiMnCiMnICMjIyBNb3JlIGFjY3VyYXRlIGluZmVyZW5jZQojJyAKIycgRHVyaW5nIGFsbCB0aGUgaXRlcmF0aXZlIG1vZGVsIGJ1aWxkaW5nIHdlIGZhdm9yZWQgb3B0aW1pemF0aW9uIGFuZAojJyBzaG9ydCBNQ01DIGNoYWlucy4gSW4gdGhlIGVuZCB3ZSBhbHNvIHJ1biB3aXRoIGhpZ2hlciBhZGFwdF9kZWx0YQojJyB0byByZWR1Y2UgdGhlIHByb2JhYmlsaXR5IG9mIGRpdmVyZ2VuY2VzLCBoaWdoZXIgbWF4aW11bSB0cmVlZGVwdGgKIycgdG8gZW5zdXJlIGhpZ2hlciBlZmZlY3RpdmUgc2FtcGxlIHNpemUgcGVyIGl0ZXJhdGlvbiAoRVNTIHBlcgojJyBzZWNvbmQgZG9lc24ndCBuZWNlc3NhcmlseSBpbXByb3ZlKSwgYW5kIHJ1biBtdWNoIGxvbmdlciBjaGFpbnMsCiMnIGJ1dCBkaWRuJ3Qgc2VlIHByYWN0aWNhbCBkaWZmZXJlbmNlcyBpbiBwbG90cyBvciBMT08tQ1YgdmFsdWVzLiBBcwojJyBydW5uaW5nIHRoZXNlIGxvbmdlciBjaGFpbnMgY2FuIHRha2UgaG91cnMgdGhleSBhcmUgbm90IHJ1biBhcyBwYXJ0CiMnIG9mIHRoaXMgbm90ZWJvb2suIEFuIGV4YW1wbGUgb2YgaG93IHRvIHJlZHVjZSBwcm9iYWJpbGl0eSBvZgojJyBkaXZlcmdlbmNlcyBhbmQgaW5jcmVhc2UgbWF4aW11bSB0cmVlZGVwdGggaXMgc2hvd24gYmVsb3cgKHRoZXJlIGlzCiMnIHJhcmVseSBuZWVkIHRvIGluY3JlYXNlIGFkYXB0X2RlbHRhIGxhcmdlciB0aGFuIDAuOTUgYW5kIGlmIHRoZXJlCiMnIGFyZSBzdGlsbCBkaXZlcmdlbmNlcyB3aXRoIGFkYXB0X2RlbHRhIGVxdWFsIHRvIDAuOTksIHRoZSBwb3N0ZXJpb3IKIycgaGFzIHNlcmlvdXMgcHJvYmxlbXMgYW5kIGl0IHNob3VsZCBiZSBjb25zaWRlcmVkIHdoZXRoZXIKIycgcmUtcGFyYW1ldGVyaXphdGlvbiwgYmV0dGVyIGRhdGEgb3IgbW9yZSBpbmZvcm1hdGl2ZSBwcmlvcnMgY291bGQKIycgaGVscCkuCiMjIGZpdDh0bnUgPC0gbW9kZWw4dG51JHNhbXBsZShkYXRhPXN0YW5kYXRhOCwgY2hhaW5zPTQsIHBhcmFsbGVsX2NoYWlucz00LAojIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWRhcHRfZGVsdGE9MC45NSwgbWF4X3RyZWVkZXB0aD0xNSkK